V10/cmd/picasso/print.c

Compare this file to the similar file:
Show the results in this format:

/*	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:print.c	1.0	*/

#include	<assert.h>
#include	<ctype.h>
#include	<string.h>
#include	"picasso.h"
#include	"y.tab.h"

extern int  eqn_count;
int	flyback;
int	redo_gbox = 0;
int	objcount  = 0;

print_buf()
{
	int	n;
	obj	*p;

	if (++objcount > objbuf) {
		p = objhead->o_next;
		if (p->o_type != BLOCK)
			print_obj(p->o_layer, p);
		else if (p->o_val[N_VAL].o == (obj *)0)
			return;
		else for (n = draftlayer; n <= top_layer; n++)
			print_obj(n,p);
		freenode(p);
	}
}

extern	FILE	*pipefp, *eqnfp;
extern	char	psfname[];

print(c)		/* show everything (above draft layers) */
	int	c;
{
	int	n;

	/* Added 10/15/90--DBK.  Is there any reason NOT to do this? */
	redo_gbox = 1;
	if (pipefp) {
		pclose(pipefp);
		pipefp = NULL;
		if ((eqnfp = fopen(psfname,"r")) == NULL)
			fatal("cannot read eqn output");
	}
	flyback = (c == 'F');
	if (c != 'N')
		for (n = draftlayer; n <= top_layer; ++n)
			print_layer(n);
	if (eqnfp) {
		fclose(eqnfp);
		eqnfp = NULL;
		eqn_count = 0;
		unlink(psfname);
	}
}

print_layer(n)	/* show contents of a single layer (maybe a draft layer) */
	int	n;
{
	obj	*p;

	for (p = objhead->o_next; p!= objtail; p = p->o_next)
		p = print_obj(n, p);
}

print_bnd(p, q)	/* show everything (non-draft) between given bounds */
	obj	*p, *q;
{
	int	n;

	for (n = draftlayer; n <= top_layer; ++n)
		print_layer_bnd(n, p, q);
}

print_layer_bnd(n, p, q)	/* show objects in layer n from p to q */
	int	n;
	obj	*p, *q;
{
	obj	*r;
	float	x0, y0, x1, y1, bnd[4];

	if (p->o_x < q->o_x)
		{ x0 = p->o_x;	x1 = q->o_x; }
	else
		{ x0 = q->o_x;	x1 = p->o_x; }
	if (p->o_y < q->o_y)
		{ y0 = p->o_y;	y1 = q->o_y; }
	else
		{ y0 = q->o_y;	y1 = p->o_y; }

	for (r = objhead->o_next; r!= objtail; r = r->o_next)
		if (r->o_x >= x0 && r->o_x <= x1
		&&  r->o_y >= y0 && r->o_y <= y1)
			r = print_obj(n, r);
}

obj	*print_obj(layer, p)
	int	layer;
	obj	*p;
{
	double	r, dx, dy, ox, oy, x0, y0, x1, y1;
	obj	*q;
	int	n;

	if (redo_gbox) {
		float	bnd[4];
		Gbox[2] = Gbox[3] = -(Gbox[0] = Gbox[1] = 32767);
		for (q = objhead->o_next; q != objtail; q = q->o_next) {
			get_bounds(q, bnd, 1);
			track_bounds (bnd[0], bnd[1], bnd[2], bnd[3]);
			if (q->o_type == BLOCK)
				q = q->o_val[N_VAL].o;
		}
		redo_gbox = 0;
	}
	openpl("");
	if (p->o_type != BLOCK && p->o_layer != layer)
		return p;
	if (p->o_type <= TEXT && (p->o_mxx!=1 || p->o_myy!=1 || p->o_mxy!=0 ||
				  p->o_myx!=0 || p->o_mxt!=0 || p->o_myt!=0))
		return print_xform(layer,p);

	ox = p->o_x;
	oy = p->o_y;
	if (p->o_type < TEXT && (p->o_attr & (FILLED | EDGED)))
		chk_attrs (p);
	switch (p->o_type) {

	case TROFF:
		n = p->o_nt1;
		if (text[n].t_type & EQNTXT)
			puteqn(ox, oy, text[n].t_type, atoi(text[n].t_val));
		else
			troff(text[n].t_val);
		return p;
	case BLOCK:
		for (q = p->o_next; q != p->o_val[N_VAL].o; q = q->o_next)
			if (q->o_type <= TEXT || q->o_nt2 > q->o_nt1)
				q = print_obj(layer,q);
		p = q;
		break;
	case PSFILE:
		puteps(p);
		/* CAREFUL!! THIS FLOWS THROUGH INTO BOX!! */
	case BOX:
		if (p->o_attr & (FILLED|EDGED)) {
			x0 = ox - p->o_wid/2;	x1 = ox + p->o_wid/2;
			y0 = oy - p->o_ht/2;	y1 = oy + p->o_ht/2;
			r  = p->o_val[N_VAL].f;
			box(x0, y0, x1, y1, r);
		}
		break;
	case CIRCLE:
	case ELLIPSE:
		if (p->o_attr & (FILLED|EDGED))
			ellipse(ox,oy,p->o_wid/2,0.,0.,p->o_ht/2,0.,2*M_PI,0);
		break;
	case SECTOR:
	case ARC:
		if (p->o_attr & (FILLED|EDGED)) {
			register double ang1, ang2;

			if (p->o_attr & HEAD12) {
				print_xform(layer, p);
				break;
			}
			r  = p->o_val[N_VAL+0].f;
			x0 = p->o_val[N_VAL+2].f;	/* starting point */
			y0 = p->o_val[N_VAL+3].f;
			x1 = p->o_val[N_VAL+4].f;	/* ending point   */
			y1 = p->o_val[N_VAL+5].f;
			ang1 = atan2(y0-oy, x0-ox);
			ang2 = atan2(y1-oy, x1-ox);
			ellipse(ox, oy, r, 0., 0., r, ang1, ang2, p->o_type);
		}
		break;
	case LINE:
	case ARROW:
	case SPLINE:
		if (p->o_attr & (FILLED|EDGED)) {
			int	c, nxy;

			if (p->o_attr & HEAD12) {
				print_xform(layer, p);
				break;
			}
			r   = p->o_val[N_VAL+0].f;
			nxy = p->o_val[N_VAL+3].f;	    /* segment count */
			x0  = p->o_val[N_VAL+4].f;	    /* first point   */
			y0  = p->o_val[N_VAL+5].f;
			x1  = p->o_val[N_VAL+4+2*nxy].f;    /* last point    */
			y1  = p->o_val[N_VAL+5+2*nxy].f;
			c = (x0 == x1 && y0 == y1);	    /* flags closure */
			if (nxy == 1)
				line(x0, y0, x1, y1);
			else if (p->o_type == SPLINE)
				spline(nxy, c, &p->o_val[N_VAL+4]);
			else
				pline (nxy, c, &p->o_val[N_VAL+4], r);
		}
		break;
	}
	if (p->o_nt1 < p->o_nt2)
		objtext(ox, oy, p);
	return p;
}

obj	*print_xform (layer,p)
	int	layer;
	obj	*p;
{
	double	r, ox, oy, dx, dy, x0, y0, x1, y1, M[4];
	double	b, tx0, ty0, tx1, ty1;
	valtype	*X;
	obj	*q;
	int	n;

	if (p->o_type == BLOCK) {
		for (q = p->o_next; q != p->o_val[N_VAL].o; q = q->o_next)
			if (q->o_type <= TEXT || q->o_nt2 > q->o_nt1)
				q = print_xform(layer,q);
		p = q;
	}
	if (p->o_layer != layer && p->o_type != BLOCK)
		return p;
#if 0
	if (p->o_type == TEXT) {
		ox = Xformx(p->o_parent, 1, p->o_x, p->o_y);
		oy = Xformy(p->o_parent, 0, p->o_x, p->o_y);
	}
	else {
#endif
		ox = Xformx(p, 1, p->o_x, p->o_y);
		oy = Xformy(p, 0, p->o_x, p->o_y);
#if 0
	}
#endif
	X = (valtype *)0;	
	if (p->o_type < TEXT && (p->o_attr & (FILLED | EDGED)))
		chk_attrs (p);

	switch (p->o_type) {

	case TROFF:
		n = p->o_nt1;
		if (text[n].t_type & EQNTXT)
			puteqn(ox, oy, text[n].t_type, atoi(text[n].t_val));
		else
			troff(text[n].t_val);
		return p;
	case PSFILE:
		puteps(p);
		/* CAREFUL!! THIS FLOWS THROUGH INTO BOX!! */
	case BOX:
		if (p->o_attr & (FILLED|EDGED)) {
			if ((X = (valtype *)malloc(10*sizeof(valtype))) == NULL)
				yyerror("out of room in print_xform");
			r = p->o_val[N_VAL].f;
			X[6].f = X[0].f = -(X[2].f = X[4].f = p->o_wid/2);
			X[1].f = X[3].f = -(X[5].f = X[7].f = p->o_ht/2);
			for (n = 0; n < 8; n += 2) {
				x1	 = ox + Linx(p, 0, X[n].f, X[n+1].f);
		  		X[n+1].f = oy + Liny(p, 0, X[n].f, X[n+1].f);
				X[n].f	 = x1;
			}
			X[n] = X[0];	X[++n] = X[1];
			x1 = Linx(p, 0, r, 0.);
			r =  Liny(p, 0, r, 0.);
			r = sqrt(x1 * x1 + r * r);
			pline(4, 1, X, r);
		}
		break;
	case CIRCLE:
	case ELLIPSE:
		if (p->o_attr & (FILLED|EDGED)) {
			get_matrix(&x0, &y0, &x1, &y1);
			x0 *= p->o_wid/2;
			y0 *= p->o_wid/2;
			x1 *= p->o_ht/2;
			y1 *= p->o_ht/2;
			ellipse(ox, oy, x0, y0, x1, y1, 0., 2*M_PI, 0);
		}
		break;
	case SECTOR:
	case ARC:
		if (p->o_attr & (FILLED|EDGED)) {
		    register double ang1, ang2;
		    double  xa, ya;
		    double  dx0, dy0, dx1, dy1;

		    r  = p->o_val[N_VAL+0].f;
		    x0 = p->o_val[N_VAL+2].f;	/* starting point */
		    y0 = p->o_val[N_VAL+3].f;
		    x1 = p->o_val[N_VAL+4].f;	/* ending point   */
		    y1 = p->o_val[N_VAL+5].f;
		    get_matrix(M, M+1, M+2, M+3);
	/*
	 *	If there are arrowheads and non-zero line thickness, we
	 *	should adjust the end points so as to get nice arrowheads.
	 */
		    if (p->o_attr & HEAD12) {
                    	dx0 = Xformx(p, 1, x0, y0);	/* Remember */
		    	dy0 = Xformy(p, 0, x0, y0);	/* directions for */
		    	dx1 = Xformx(p, 0, x1, y1);	/* arrowheads */
		    	dy1 = Xformy(p, 0, x1, y1);
		    /* in here we need to change the points used to compute
		       the angles. */
			dx = p->o_val[N_VAL+8].f;
			dy = p->o_val[N_VAL+9].f;
			if (p->o_weight > 0.) {
			    double	linex, liney, a;

			    b = p->o_weight / 2 / p->o_val[N_VAL+8].f;
			    b *= sqrt(dx*dx + 4*dy*dy);
			    if (p->o_attr & HEAD2) {
				linex = - (y1 - p->o_y);
				liney = (x1 - p->o_x);
				a = b / sqrt(linex*linex + liney*liney);
				x1 -= a * linex;
				y1 -= a * liney;
			    }
			    if (p->o_attr & HEAD1) {
				linex = (y0 - p->o_y);
				liney = - (x0 - p->o_x);
				a = b / sqrt(linex*linex + liney*liney);
				x0 -= a * linex;
				y0 -= a * liney;
			    }
			}
		    }
                    tx0 = Xformx(p, 1, x0, y0); /* transformed starting point */
		    ty0 = Xformy(p, 0, x0, y0);
		    tx1 = Xformx(p, 0, x1, y1);   /* transformed ending point */
		    ty1 = Xformy(p, 0, x1, y1);
		    ang1 = atan2(ty0 - oy, tx0 - ox);
		    ang2 = atan2(ty1 - oy, tx1 - ox);

		    dx = M[0] * M[3] - M[1] * M[2];
		    if (dx < 0) {			/* reflection */
			xa = ang1;
			ang1 = ang2;
			ang2 = xa;
			M[0] = -M[0];
			M[2] = -M[2];
		    }
		    ellipse(ox, oy, r*M[0], r*M[1], r*M[2], r*M[3],
					ang1, ang2, p->o_type);

		    if (p->o_attr & (HEAD1 | HEAD2)) {
			ang1 = 0;
			if (dx < 0) {
			    ang1 = M_PI;
			    dx = -dx;
			}
			dy = dx = sqrt(dx);
			dx *= p->o_val[N_VAL+8].f;
			dy *= p->o_val[N_VAL+9].f;
			if (p->o_attr & HEAD1)
			    arrow(tx0-(dy0-oy), ty0+(dx0-ox), tx0, ty0,
					dx, dy, dy/r/2 + ang1, p->o_attr);
			if (p->o_attr & HEAD2)
			    arrow(tx1+(dy1-oy), ty1-(dx1-ox), tx1, ty1,
					dx, dy, -dy/r/2 + ang1, p->o_attr);
		    }
		}
		break;
	case LINE:
	case ARROW:
	case SPLINE:
		if (p->o_attr & (FILLED|EDGED)) {
			int	c, i, nxy;

			r   = p->o_val[N_VAL+0].f;
			x1 = Linx(p, 0, r, 0.);
			r =  Liny(p, 0, r, 0.);
			r = sqrt(x1 * x1 + r * r);
			nxy = p->o_val[N_VAL+3].f;	/* segment count */
			X = (valtype *)malloc((2*nxy+2)*sizeof(valtype));
			if (X == NULL)
				yyerror("out of room in print_xform");
			for (i = 0, n = N_VAL+4; i <= 2 * nxy; ) {
				register double	xx = p->o_val[n++].f,
						yy = p->o_val[n++].f;
				X[i++].f = Xformx(p, 0, xx, yy);
				X[i++].f = Xformy(p, 0, xx, yy);
			}
			x0 = X[0].f;
			y0 = X[1].f;
			x1 = X[i-2].f;
			y1 = X[i-1].f;
			tx0 = ty0 = tx1 = ty1 = 0.;
			n = 2 * nxy - 2;
			if (p->o_attr & HEAD12) {
			    get_matrix(M, M+1, M+2, M+3);
		/*  DBK: I added the fabs to eliminate sqrt errors
		 *  and make it same as xprint.c.  9/20/90	*/
			    dy = dx = sqrt(fabs(M[0]*M[3] - M[1]*M[2]));
			    dx *= p->o_val[N_VAL+1].f;
			    dy *= p->o_val[N_VAL+2].f;
			    if (p->o_weight > 0.) {
				double	linex, liney, a;

				b = p->o_weight / 2 / p->o_val[N_VAL+1].f;
				b *= sqrt(dx*dx + 4*dy*dy);
				if (p->o_attr & HEAD2) {
				    linex = x1 - X[n].f;
				    liney = y1 - X[n+1].f;
				    a = b / sqrt(linex*linex + liney*liney);
				    tx1 = -a * linex;
				    ty1 = -a * liney;
				    x1 = X[n+2].f += tx1;
				    y1 = X[n+3].f += ty1;
				}
				if (p->o_attr & HEAD1) {
				    linex = x0 - X[2].f;
				    liney = y0 - X[3].f;
				    a = b / sqrt(linex*linex + liney*liney);
				    tx0 = -a * linex;
				    ty0 = -a * liney;
				    x0 = X[0].f += tx0;
				    y0 = X[1].f += ty0;
				}
			    }
			}
                /*      The first two args are just to give a direction to
                 *      the second two.  To make sure that the direction
                 *      isn't reversed, adjust the first two by the same
                 *      amount as we adjusted x1 and y1 above.
                 */
			c = (x0 == x1 && y0 == y1);	    /* flags closure */
			if (nxy == 1)
				line(X[0].f, X[1].f, X[2].f, X[3].f);
			else if (p->o_type == SPLINE)
				spline(nxy, c, X);
			else
				pline (nxy, c, X, r);
                        if (p->o_attr & HEAD2) {
                            tx1 += X[n].f;
                            ty1 += X[n+1].f;
                            arrow(tx1, ty1, x1, y1, dx, dy, 0.0, p->o_attr);
                        }
                        if (p->o_attr & HEAD1) {
                            tx0 += X[2].f;
                            ty0 += X[3].f;
                            arrow(tx0, ty0, x0, y0, dx, dy, 0.0, p->o_attr);
                        }
		}
		break;
	case TEXT:
		tmp_xform(p);
#if 0
		dotext(ox, oy, p);
#else
		dotext(p->o_x, p->o_y, p);
#endif
		undo_tmpx();
		return p;
	}
	if (X)
		free(X);
	if (p->o_nt1 < p->o_nt2)
		objtext(ox, oy, p);
	return p;
}

objtext(x, y, p)
	double x, y;
	obj    *p;
{
	double  *bnd;
	int     i, t;

	t = text[p->o_nt1].t_type;
	for (i = p->o_nt1; i < p->o_nt2; i++)
		if (text[i].t_type != t)
			break;
	if (i >= p->o_nt2 && p->o_type != TEXT) {  /* all strings same type */
		bnd = text_bounds(p);
		if (t & RJUST)
			x += (bnd[2] - bnd[0]) / 2;
		if (t & LJUST)
			x -= (bnd[2] - bnd[0]) / 2;
	}
	dotext(x, y, p);
}

dotext(x, y, p)	/* print text strings of p in proper vertical spacing   */
	double x, y;
	obj *p;
{
	double	h, v, w, dely;
	int	i, j, n, t;

	i = p->o_nt1;
	j = text[i].t_line;			/* sequence # of first line   */
	n = text[p->o_nt2-1].t_line - j;	/* total number of lines (-1) */
	v = abs(text[i].t_size) / (2 * pgscale);
	dely = abs(text[i].t_space) / (2 * pgscale);
	v = n * dely - v/2;
	new_color(p->o_text);
	for (h = w = 0; i < p->o_nt2; ++j, v -= 2*dely, h = w = 0) {
		t = text[i].t_type;
		if (t & ABOVE)
			v += dely;
		else if (t & BELOW)
			v -= dely;
		for (n = i; text[n].t_line == j; n++)
			w += text[n].t_width*72/pgscale;
		if (t & RJUST)
			h = w;
		else if (t & CENTER)
			h = w/2;
		newlabel(t, text[i].t_val, abs(text[i].t_font), x-h, y+v,
						text[i].t_size / pgscale,
						text[i].t_width * 72 / pgscale);
		while (++i < n)
			addlabel(text[i].t_type, text[i].t_val,
				 text[i].t_font, text[i].t_size / pgscale,
					    text[i].t_width * 72 / pgscale);
	}
}