xref: /inferno-os/libtk/cpoly.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "draw.h"
3*37da2899SCharles.Forsyth #include "tk.h"
4*37da2899SCharles.Forsyth #include "canvs.h"
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
7*37da2899SCharles.Forsyth 
8*37da2899SCharles.Forsyth typedef struct TkCpoly TkCpoly;
9*37da2899SCharles.Forsyth struct TkCpoly
10*37da2899SCharles.Forsyth {
11*37da2899SCharles.Forsyth 	int		width;
12*37da2899SCharles.Forsyth 	Image*		stipple;
13*37da2899SCharles.Forsyth 	Image*		pen;
14*37da2899SCharles.Forsyth 	TkCanvas*	canv;
15*37da2899SCharles.Forsyth 	int		smooth;
16*37da2899SCharles.Forsyth 	int		steps;
17*37da2899SCharles.Forsyth 	int		winding;
18*37da2899SCharles.Forsyth };
19*37da2899SCharles.Forsyth 
20*37da2899SCharles.Forsyth static
21*37da2899SCharles.Forsyth TkStab tkwinding[] =
22*37da2899SCharles.Forsyth {
23*37da2899SCharles.Forsyth 	"nonzero",	~0,
24*37da2899SCharles.Forsyth 	"odd",		1,
25*37da2899SCharles.Forsyth 	nil
26*37da2899SCharles.Forsyth };
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth /* Polygon Options (+ means implemented)
29*37da2899SCharles.Forsyth 	+fill
30*37da2899SCharles.Forsyth 	+smooth
31*37da2899SCharles.Forsyth 	+splinesteps
32*37da2899SCharles.Forsyth 	+stipple
33*37da2899SCharles.Forsyth 	+tags
34*37da2899SCharles.Forsyth 	+width
35*37da2899SCharles.Forsyth 	+outline
36*37da2899SCharles.Forsyth */
37*37da2899SCharles.Forsyth static
38*37da2899SCharles.Forsyth TkOption polyopts[] =
39*37da2899SCharles.Forsyth {
40*37da2899SCharles.Forsyth 	"width",	OPTnnfrac,	O(TkCpoly, width),	nil,
41*37da2899SCharles.Forsyth 	"stipple",	OPTbmap,	O(TkCpoly, stipple),	nil,
42*37da2899SCharles.Forsyth 	"smooth",	OPTstab,	O(TkCpoly, smooth),	tkbool,
43*37da2899SCharles.Forsyth 	"splinesteps",	OPTdist,	O(TkCpoly, steps),	nil,
44*37da2899SCharles.Forsyth 	"winding",	OPTstab, O(TkCpoly, winding), tkwinding,
45*37da2899SCharles.Forsyth 	nil
46*37da2899SCharles.Forsyth };
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth static
49*37da2899SCharles.Forsyth TkOption itemopts[] =
50*37da2899SCharles.Forsyth {
51*37da2899SCharles.Forsyth 	"tags",		OPTctag,	O(TkCitem, tags),	nil,
52*37da2899SCharles.Forsyth 	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCfill),
53*37da2899SCharles.Forsyth 	"outline",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),
54*37da2899SCharles.Forsyth 	nil
55*37da2899SCharles.Forsyth };
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth void
tkcvspolysize(TkCitem * i)58*37da2899SCharles.Forsyth tkcvspolysize(TkCitem *i)
59*37da2899SCharles.Forsyth {
60*37da2899SCharles.Forsyth 	int w;
61*37da2899SCharles.Forsyth 	TkCpoly *p;
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth 	p = TKobj(TkCpoly, i);
64*37da2899SCharles.Forsyth 	w = TKF2I(p->width);
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth 	i->p.bb = bbnil;
67*37da2899SCharles.Forsyth 	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
68*37da2899SCharles.Forsyth 	i->p.bb = insetrect(i->p.bb, -w);
69*37da2899SCharles.Forsyth }
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth char*
tkcvspolycreat(Tk * tk,char * arg,char ** val)72*37da2899SCharles.Forsyth tkcvspolycreat(Tk* tk, char *arg, char **val)
73*37da2899SCharles.Forsyth {
74*37da2899SCharles.Forsyth 	char *e;
75*37da2899SCharles.Forsyth 	TkCpoly *p;
76*37da2899SCharles.Forsyth 	TkCitem *i;
77*37da2899SCharles.Forsyth 	TkCanvas *c;
78*37da2899SCharles.Forsyth 	TkOptab tko[3];
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth 	i = tkcnewitem(tk, TkCVpoly, sizeof(TkCitem)+sizeof(TkCpoly));
83*37da2899SCharles.Forsyth 	if(i == nil)
84*37da2899SCharles.Forsyth 		return TkNomem;
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 	p = TKobj(TkCpoly, i);
87*37da2899SCharles.Forsyth 	p->width = TKI2F(1);
88*37da2899SCharles.Forsyth 	p->winding = ~0;
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth 	e = tkparsepts(tk->env->top, &i->p, &arg, 1);
91*37da2899SCharles.Forsyth 	if(e == nil && i->p.npoint < 3)
92*37da2899SCharles.Forsyth 		e = TkBadvl;
93*37da2899SCharles.Forsyth 	if(e != nil) {
94*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
95*37da2899SCharles.Forsyth 		return e;
96*37da2899SCharles.Forsyth 	}
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth 	tko[0].ptr = p;
99*37da2899SCharles.Forsyth 	tko[0].optab = polyopts;
100*37da2899SCharles.Forsyth 	tko[1].ptr = i;
101*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
102*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
103*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
104*37da2899SCharles.Forsyth 	if(e != nil) {
105*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
106*37da2899SCharles.Forsyth 		return e;
107*37da2899SCharles.Forsyth 	}
108*37da2899SCharles.Forsyth 	p->canv = c;
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth 	e = tkcaddtag(tk, i, 1);
111*37da2899SCharles.Forsyth 	if(e != nil) {
112*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
113*37da2899SCharles.Forsyth 		return e;
114*37da2899SCharles.Forsyth 	}
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth 	tkcvspolysize(i);
117*37da2899SCharles.Forsyth 	tkmkpen(&p->pen, i->env, p->stipple);
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth 	e = tkvalue(val, "%d", i->id);
120*37da2899SCharles.Forsyth 	if(e != nil) {
121*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
122*37da2899SCharles.Forsyth 		return e;
123*37da2899SCharles.Forsyth 	}
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth 	tkcvsappend(c, i);
126*37da2899SCharles.Forsyth 	tkbbmax(&c->update, &i->p.bb);
127*37da2899SCharles.Forsyth 	tkcvssetdirty(tk);
128*37da2899SCharles.Forsyth 	return nil;
129*37da2899SCharles.Forsyth }
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth char*
tkcvspolycget(TkCitem * i,char * arg,char ** val)132*37da2899SCharles.Forsyth tkcvspolycget(TkCitem *i, char *arg, char **val)
133*37da2899SCharles.Forsyth {
134*37da2899SCharles.Forsyth 	TkOptab tko[3];
135*37da2899SCharles.Forsyth 	TkCpoly *p = TKobj(TkCpoly, i);
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth 	tko[0].ptr = p;
138*37da2899SCharles.Forsyth 	tko[0].optab = polyopts;
139*37da2899SCharles.Forsyth 	tko[1].ptr = i;
140*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
141*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, i->env->top);
144*37da2899SCharles.Forsyth }
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth char*
tkcvspolyconf(Tk * tk,TkCitem * i,char * arg)147*37da2899SCharles.Forsyth tkcvspolyconf(Tk *tk, TkCitem *i, char *arg)
148*37da2899SCharles.Forsyth {
149*37da2899SCharles.Forsyth 	char *e;
150*37da2899SCharles.Forsyth 	TkOptab tko[3];
151*37da2899SCharles.Forsyth 	TkCpoly *p = TKobj(TkCpoly, i);
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth 	tko[0].ptr = p;
154*37da2899SCharles.Forsyth 	tko[0].optab = polyopts;
155*37da2899SCharles.Forsyth 	tko[1].ptr = i;
156*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
157*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
160*37da2899SCharles.Forsyth 
161*37da2899SCharles.Forsyth 	tkcvspolysize(i);
162*37da2899SCharles.Forsyth 	tkmkpen(&p->pen, i->env, p->stipple);
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth 	return e;
165*37da2899SCharles.Forsyth }
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth void
tkcvspolyfree(TkCitem * i)168*37da2899SCharles.Forsyth tkcvspolyfree(TkCitem *i)
169*37da2899SCharles.Forsyth {
170*37da2899SCharles.Forsyth 	TkCpoly *p;
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth 	p = TKobj(TkCpoly, i);
173*37da2899SCharles.Forsyth 	if(p->stipple)
174*37da2899SCharles.Forsyth 		freeimage(p->stipple);
175*37da2899SCharles.Forsyth 	if(p->pen)
176*37da2899SCharles.Forsyth 		freeimage(p->pen);
177*37da2899SCharles.Forsyth }
178*37da2899SCharles.Forsyth 
179*37da2899SCharles.Forsyth void
tkcvspolydraw(Image * img,TkCitem * i,TkEnv * pe)180*37da2899SCharles.Forsyth tkcvspolydraw(Image *img, TkCitem *i, TkEnv *pe)
181*37da2899SCharles.Forsyth {
182*37da2899SCharles.Forsyth 	int w;
183*37da2899SCharles.Forsyth 	TkEnv *e;
184*37da2899SCharles.Forsyth 	TkCpoly *p;
185*37da2899SCharles.Forsyth 	Image *pen;
186*37da2899SCharles.Forsyth 	Point *pts;
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 	USED(pe);
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth 	p = TKobj(TkCpoly, i);
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth 	e = i->env;
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth 	pen = p->pen;
195*37da2899SCharles.Forsyth 	if(pen == nil && (e->set & (1<<TkCfill)))
196*37da2899SCharles.Forsyth 		pen = tkgc(e, TkCfill);
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth 	pts = i->p.drawpt;
199*37da2899SCharles.Forsyth 	if(i->p.npoint > 0 && pen != nil) {
200*37da2899SCharles.Forsyth 		if (p->smooth == BoolT)
201*37da2899SCharles.Forsyth 			fillbezspline(img, pts, i->p.npoint+1, p->winding, pen, pts[0]);
202*37da2899SCharles.Forsyth 		else
203*37da2899SCharles.Forsyth 			fillpoly(img, pts, i->p.npoint+1, p->winding, pen, pts[0]);
204*37da2899SCharles.Forsyth 	}
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth 	w = TKF2I(p->width) - 1;
207*37da2899SCharles.Forsyth 	if(w >= 0 && (e->set & (1<<TkCforegnd))) {
208*37da2899SCharles.Forsyth 		pen = tkgc(i->env, TkCforegnd);
209*37da2899SCharles.Forsyth 		if (p->smooth == BoolT)
210*37da2899SCharles.Forsyth 			bezspline(img, pts, i->p.npoint+1, Enddisc, Enddisc, w, pen, pts[0]);
211*37da2899SCharles.Forsyth 		else
212*37da2899SCharles.Forsyth 			poly(img, pts, i->p.npoint+1, Enddisc, Enddisc, w, pen, pts[0]);
213*37da2899SCharles.Forsyth 	}
214*37da2899SCharles.Forsyth }
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth char*
tkcvspolycoord(TkCitem * i,char * arg,int x,int y)217*37da2899SCharles.Forsyth tkcvspolycoord(TkCitem *i, char *arg, int x, int y)
218*37da2899SCharles.Forsyth {
219*37da2899SCharles.Forsyth 	char *e;
220*37da2899SCharles.Forsyth 	TkCpoints p;
221*37da2899SCharles.Forsyth 
222*37da2899SCharles.Forsyth 	if(arg == nil) {
223*37da2899SCharles.Forsyth 		tkxlatepts(i->p.parampt, i->p.npoint, x, y);
224*37da2899SCharles.Forsyth 		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
225*37da2899SCharles.Forsyth 		i->p.drawpt[i->p.npoint] = i->p.drawpt[0];
226*37da2899SCharles.Forsyth 		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
227*37da2899SCharles.Forsyth 	}
228*37da2899SCharles.Forsyth 	else {
229*37da2899SCharles.Forsyth 		e = tkparsepts(i->env->top, &p, &arg, 1);
230*37da2899SCharles.Forsyth 		if(e != nil)
231*37da2899SCharles.Forsyth 			return e;
232*37da2899SCharles.Forsyth 		if(p.npoint < 2) {
233*37da2899SCharles.Forsyth 			tkfreepoint(&p);
234*37da2899SCharles.Forsyth 			return TkFewpt;
235*37da2899SCharles.Forsyth 		}
236*37da2899SCharles.Forsyth 		tkfreepoint(&i->p);
237*37da2899SCharles.Forsyth 		i->p = p;
238*37da2899SCharles.Forsyth 		tkcvspolysize(i);
239*37da2899SCharles.Forsyth 	}
240*37da2899SCharles.Forsyth 	return nil;
241*37da2899SCharles.Forsyth }
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth int
tkcvspolyhit(TkCitem * item,Point p)244*37da2899SCharles.Forsyth tkcvspolyhit(TkCitem *item, Point p)
245*37da2899SCharles.Forsyth {
246*37da2899SCharles.Forsyth 	Point *poly;
247*37da2899SCharles.Forsyth 	int r, np, fill, w;
248*37da2899SCharles.Forsyth 	TkCpoly *l;
249*37da2899SCharles.Forsyth 	TkEnv *e;
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth 	l = TKobj(TkCpoly, item);
252*37da2899SCharles.Forsyth 	w = TKF2I(l->width) + 2;		/* include some slop */
253*37da2899SCharles.Forsyth 	e = item->env;
254*37da2899SCharles.Forsyth 	fill = e->set & (1<<TkCfill);
255*37da2899SCharles.Forsyth 	if (l->smooth == BoolT) {
256*37da2899SCharles.Forsyth 		/* this works but it's slow if used intensively... */
257*37da2899SCharles.Forsyth 		np = getbezsplinepts(item->p.drawpt, item->p.npoint + 1, &poly);
258*37da2899SCharles.Forsyth 		if (fill)
259*37da2899SCharles.Forsyth 			r = tkinsidepoly(poly, np, l->winding, p);
260*37da2899SCharles.Forsyth 		else
261*37da2899SCharles.Forsyth 			r = tklinehit(poly, np, w, p);
262*37da2899SCharles.Forsyth 		free(poly);
263*37da2899SCharles.Forsyth 	} else {
264*37da2899SCharles.Forsyth 		if (fill)
265*37da2899SCharles.Forsyth 			r = tkinsidepoly(item->p.drawpt, item->p.npoint, l->winding, p);
266*37da2899SCharles.Forsyth 		else
267*37da2899SCharles.Forsyth 			r = tklinehit(item->p.drawpt, item->p.npoint + 1, w, p);
268*37da2899SCharles.Forsyth 	}
269*37da2899SCharles.Forsyth 	return r;
270*37da2899SCharles.Forsyth }
271