Charles.Forsyth20060303a828770d19 years agoHistory
280 lines · 4.9 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h"#include "canvs.h" #define	O(t, e)		((long)(&((t*)0)->e))typedef void	(*Drawfn)(Image*, Point, int, int, Image*, int); /* Arc Options (+ means implemented)	+extent	+fill	+outline	 outlinestipple	+start 	+stipple	+style (+pieslice chord +arc)	+tags	+width*/ typedef struct TkCarc TkCarc;struct TkCarc{	int	width;	int 	start;	int 	extent;	int 	style;	Image*	stipple;	Image*	pen;}; enum Style{	Pieslice,	Chord,	Arc}; static TkStab tkstyle[] ={	"pieslice",	Pieslice,	"arc",		Arc,	"chord",	Arc,	/* Can't do chords */	nil}; staticTkOption arcopts[] ={	"start",	OPTfrac,	O(TkCarc, start),	nil,	"extent",	OPTfrac,	O(TkCarc, extent),	nil,	"style",	OPTstab,	O(TkCarc, style),	tkstyle,	"width",	OPTnnfrac,	O(TkCarc, width),	nil,	"stipple",	OPTbmap,	O(TkCarc, stipple),	nil,	nil}; staticTkOption itemopts[] ={	"tags",		OPTctag,	O(TkCitem, tags),	nil,	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCfill),	"outline",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),	nil}; voidtkcvsarcsize(TkCitem *i){	int w;	TkCarc *a; 	a = TKobj(TkCarc, i);	w = TKF2I(a->width)*2; 	i->p.bb = bbnil;	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);	i->p.bb = insetrect(i->p.bb, -w);} char*tkcvsarccreat(Tk* tk, char *arg, char **val){	char *e;	TkCarc *a;	TkCitem *i;	TkCanvas *c;	TkOptab tko[3]; 	c = TKobj(TkCanvas, tk); 	i = tkcnewitem(tk, TkCVarc, sizeof(TkCitem)+sizeof(TkCarc));	if(i == nil)		return TkNomem; 	a = TKobj(TkCarc, i);	a->width = TKI2F(1); 	e = tkparsepts(tk->env->top, &i->p, &arg, 0);	if(e != nil) {		tkcvsfreeitem(i);		return e;	}	if(i->p.npoint != 2) {		tkcvsfreeitem(i);		return TkFewpt;	} 	tko[0].ptr = a;	tko[0].optab = arcopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil;	e = tkparse(tk->env->top, arg, tko, nil);	if(e != nil) {		tkcvsfreeitem(i);		return e;	}		e = tkcaddtag(tk, i, 1);	if(e != nil) {		tkcvsfreeitem(i);		return e;	} 	tkcvsarcsize(i);	tkmkpen(&a->pen, i->env, a->stipple); 	tkcvsappend(c, i); 	tkbbmax(&c->update, &i->p.bb);	tkcvssetdirty(tk);	return tkvalue(val, "%d", i->id);} char*tkcvsarccget(TkCitem *i, char *arg, char **val){	TkOptab tko[3];	TkCarc *a = TKobj(TkCarc, i); 	tko[0].ptr = a;	tko[0].optab = arcopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil; 	return tkgencget(tko, arg, val, i->env->top);} char*tkcvsarcconf(Tk *tk, TkCitem *i, char *arg){	char *e;	TkOptab tko[3];	TkCarc *a = TKobj(TkCarc, i); 	tko[0].ptr = a;	tko[0].optab = arcopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil; 	e = tkparse(tk->env->top, arg, tko, nil);	tkcvsarcsize(i);	tkmkpen(&a->pen, i->env, a->stipple); 	return e;}  voidtkcvsarcfree(TkCitem *i){	TkCarc *a; 	a = TKobj(TkCarc, i);	if(a->stipple)		freeimage(a->stipple);	if(a->pen)		freeimage(a->pen);} voidtkcvsarcdraw(Image *img, TkCitem *i, TkEnv *pe){	TkEnv *e;	TkCarc *a;	Rectangle d;	int w, dx, dy;	int s, ext, s0, s1, e0, e1, l;	Image *pen, *col, *tmp;	Point p0, p1, c;	extern void drawarc(Point,int,int,int,int,int,Image *,Image *,Image *); 	USED(pe); 	d.min = i->p.drawpt[0];	d.max = i->p.drawpt[1]; 	e = i->env;	a = TKobj(TkCarc, i); 	pen = a->pen;	if(pen == nil && (e->set & (1<<TkCfill)))		pen = tkgc(e, TkCfill); 	w = TKF2I(a->width)/2;	if(w < 0)		return; 	d = canonrect(d);	dx = Dx(d)/2;	dy = Dy(d)/2;	c.x = (d.min.x+d.max.x)/2;	c.y = (d.min.y+d.max.y)/2;	s = TKF2I(a->start);	ext = TKF2I(a->extent);/*	if(ext == 0)		ext = 90;*/ 	if(a->style != Arc && pen != nil)		fillarc(img, c, dx, dy, pen, Pt(0,0), s, ext);	col = tkgc(e, TkCforegnd);	arc(img, c, dx, dy, w, col, Pt(0,0), s, ext);	if(a->style == Pieslice){		/*		 * It is difficult to compute the intersection of the lines		 * and the ellipse using integers, so let the draw library		 * do it for us: use a full ellipse as the source of color		 * for drawing the lines.		 */		tmp = allocimage(img->display, d, img->chan, 0, DNofill);		if(tmp == nil)			return;		/* copy dest to tmp so lines don't spill beyond edge of ellipse */		drawop(tmp, d, img, nil, d.min, S);		fillellipse(tmp, c, dx, dy, col, Pt(0,0));		icossin(s, &s1, &s0);		icossin(s+ext, &e1, &e0);		if(dx > dy)			l = 2*dx+1;		else			l = 2*dy+1;		p0 = Pt(c.x+l*s1/ICOSSCALE, c.y-l*s0/ICOSSCALE);		p1 = Pt(c.x+l*e1/ICOSSCALE, c.y-l*e0/ICOSSCALE);		line(img, c, p0, Endsquare, Endsquare, w, tmp, c);		line(img, c, p1, Endsquare, Endsquare, w, tmp, c);		freeimage(tmp);	}} char*tkcvsarccoord(TkCitem *i, char *arg, int x, int y){	char *e;	TkCpoints p; 	if(arg == nil) {		tkxlatepts(i->p.parampt, i->p.npoint, x, y);		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));	}	else {		e = tkparsepts(i->env->top, &p, &arg, 0);		if(e != nil)			return e;		if(p.npoint != 2) {			tkfreepoint(&p);			return TkFewpt;		}		tkfreepoint(&i->p);		i->p = p;		tkcvsarcsize(i);	}	return nil;}