xref: /inferno-os/libtk/carcs.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 typedef void	(*Drawfn)(Image*, Point, int, int, Image*, int);
8*37da2899SCharles.Forsyth 
9*37da2899SCharles.Forsyth /* Arc Options (+ means implemented)
10*37da2899SCharles.Forsyth 	+extent
11*37da2899SCharles.Forsyth 	+fill
12*37da2899SCharles.Forsyth 	+outline
13*37da2899SCharles.Forsyth 	 outlinestipple
14*37da2899SCharles.Forsyth 	+start
15*37da2899SCharles.Forsyth 	+stipple
16*37da2899SCharles.Forsyth 	+style (+pieslice chord +arc)
17*37da2899SCharles.Forsyth 	+tags
18*37da2899SCharles.Forsyth 	+width
19*37da2899SCharles.Forsyth */
20*37da2899SCharles.Forsyth 
21*37da2899SCharles.Forsyth typedef struct TkCarc TkCarc;
22*37da2899SCharles.Forsyth struct TkCarc
23*37da2899SCharles.Forsyth {
24*37da2899SCharles.Forsyth 	int	width;
25*37da2899SCharles.Forsyth 	int 	start;
26*37da2899SCharles.Forsyth 	int 	extent;
27*37da2899SCharles.Forsyth 	int 	style;
28*37da2899SCharles.Forsyth 	Image*	stipple;
29*37da2899SCharles.Forsyth 	Image*	pen;
30*37da2899SCharles.Forsyth };
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth enum Style
33*37da2899SCharles.Forsyth {
34*37da2899SCharles.Forsyth 	Pieslice,
35*37da2899SCharles.Forsyth 	Chord,
36*37da2899SCharles.Forsyth 	Arc
37*37da2899SCharles.Forsyth };
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth static
40*37da2899SCharles.Forsyth TkStab tkstyle[] =
41*37da2899SCharles.Forsyth {
42*37da2899SCharles.Forsyth 	"pieslice",	Pieslice,
43*37da2899SCharles.Forsyth 	"arc",		Arc,
44*37da2899SCharles.Forsyth 	"chord",	Arc,	/* Can't do chords */
45*37da2899SCharles.Forsyth 	nil
46*37da2899SCharles.Forsyth };
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth static
49*37da2899SCharles.Forsyth TkOption arcopts[] =
50*37da2899SCharles.Forsyth {
51*37da2899SCharles.Forsyth 	"start",	OPTfrac,	O(TkCarc, start),	nil,
52*37da2899SCharles.Forsyth 	"extent",	OPTfrac,	O(TkCarc, extent),	nil,
53*37da2899SCharles.Forsyth 	"style",	OPTstab,	O(TkCarc, style),	tkstyle,
54*37da2899SCharles.Forsyth 	"width",	OPTnnfrac,	O(TkCarc, width),	nil,
55*37da2899SCharles.Forsyth 	"stipple",	OPTbmap,	O(TkCarc, stipple),	nil,
56*37da2899SCharles.Forsyth 	nil
57*37da2899SCharles.Forsyth };
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth static
60*37da2899SCharles.Forsyth TkOption itemopts[] =
61*37da2899SCharles.Forsyth {
62*37da2899SCharles.Forsyth 	"tags",		OPTctag,	O(TkCitem, tags),	nil,
63*37da2899SCharles.Forsyth 	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCfill),
64*37da2899SCharles.Forsyth 	"outline",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),
65*37da2899SCharles.Forsyth 	nil
66*37da2899SCharles.Forsyth };
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth void
tkcvsarcsize(TkCitem * i)69*37da2899SCharles.Forsyth tkcvsarcsize(TkCitem *i)
70*37da2899SCharles.Forsyth {
71*37da2899SCharles.Forsyth 	int w;
72*37da2899SCharles.Forsyth 	TkCarc *a;
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth 	a = TKobj(TkCarc, i);
75*37da2899SCharles.Forsyth 	w = TKF2I(a->width)*2;
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth 	i->p.bb = bbnil;
78*37da2899SCharles.Forsyth 	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
79*37da2899SCharles.Forsyth 	i->p.bb = insetrect(i->p.bb, -w);
80*37da2899SCharles.Forsyth }
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth char*
tkcvsarccreat(Tk * tk,char * arg,char ** val)83*37da2899SCharles.Forsyth tkcvsarccreat(Tk* tk, char *arg, char **val)
84*37da2899SCharles.Forsyth {
85*37da2899SCharles.Forsyth 	char *e;
86*37da2899SCharles.Forsyth 	TkCarc *a;
87*37da2899SCharles.Forsyth 	TkCitem *i;
88*37da2899SCharles.Forsyth 	TkCanvas *c;
89*37da2899SCharles.Forsyth 	TkOptab tko[3];
90*37da2899SCharles.Forsyth 
91*37da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth 	i = tkcnewitem(tk, TkCVarc, sizeof(TkCitem)+sizeof(TkCarc));
94*37da2899SCharles.Forsyth 	if(i == nil)
95*37da2899SCharles.Forsyth 		return TkNomem;
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth 	a = TKobj(TkCarc, i);
98*37da2899SCharles.Forsyth 	a->width = TKI2F(1);
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth 	e = tkparsepts(tk->env->top, &i->p, &arg, 0);
101*37da2899SCharles.Forsyth 	if(e != nil) {
102*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
103*37da2899SCharles.Forsyth 		return e;
104*37da2899SCharles.Forsyth 	}
105*37da2899SCharles.Forsyth 	if(i->p.npoint != 2) {
106*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
107*37da2899SCharles.Forsyth 		return TkFewpt;
108*37da2899SCharles.Forsyth 	}
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth 	tko[0].ptr = a;
111*37da2899SCharles.Forsyth 	tko[0].optab = arcopts;
112*37da2899SCharles.Forsyth 	tko[1].ptr = i;
113*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
114*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
115*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
116*37da2899SCharles.Forsyth 	if(e != nil) {
117*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
118*37da2899SCharles.Forsyth 		return e;
119*37da2899SCharles.Forsyth 	}
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth 	e = tkcaddtag(tk, i, 1);
122*37da2899SCharles.Forsyth 	if(e != nil) {
123*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
124*37da2899SCharles.Forsyth 		return e;
125*37da2899SCharles.Forsyth 	}
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth 	tkcvsarcsize(i);
128*37da2899SCharles.Forsyth 	tkmkpen(&a->pen, i->env, a->stipple);
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth 	tkcvsappend(c, i);
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth 	tkbbmax(&c->update, &i->p.bb);
133*37da2899SCharles.Forsyth 	tkcvssetdirty(tk);
134*37da2899SCharles.Forsyth 	return tkvalue(val, "%d", i->id);
135*37da2899SCharles.Forsyth }
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth char*
tkcvsarccget(TkCitem * i,char * arg,char ** val)138*37da2899SCharles.Forsyth tkcvsarccget(TkCitem *i, char *arg, char **val)
139*37da2899SCharles.Forsyth {
140*37da2899SCharles.Forsyth 	TkOptab tko[3];
141*37da2899SCharles.Forsyth 	TkCarc *a = TKobj(TkCarc, i);
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth 	tko[0].ptr = a;
144*37da2899SCharles.Forsyth 	tko[0].optab = arcopts;
145*37da2899SCharles.Forsyth 	tko[1].ptr = i;
146*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
147*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, i->env->top);
150*37da2899SCharles.Forsyth }
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth char*
tkcvsarcconf(Tk * tk,TkCitem * i,char * arg)153*37da2899SCharles.Forsyth tkcvsarcconf(Tk *tk, TkCitem *i, char *arg)
154*37da2899SCharles.Forsyth {
155*37da2899SCharles.Forsyth 	char *e;
156*37da2899SCharles.Forsyth 	TkOptab tko[3];
157*37da2899SCharles.Forsyth 	TkCarc *a = TKobj(TkCarc, i);
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth 	tko[0].ptr = a;
160*37da2899SCharles.Forsyth 	tko[0].optab = arcopts;
161*37da2899SCharles.Forsyth 	tko[1].ptr = i;
162*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
163*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
166*37da2899SCharles.Forsyth 	tkcvsarcsize(i);
167*37da2899SCharles.Forsyth 	tkmkpen(&a->pen, i->env, a->stipple);
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth 	return e;
170*37da2899SCharles.Forsyth }
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth void
tkcvsarcfree(TkCitem * i)174*37da2899SCharles.Forsyth tkcvsarcfree(TkCitem *i)
175*37da2899SCharles.Forsyth {
176*37da2899SCharles.Forsyth 	TkCarc *a;
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth 	a = TKobj(TkCarc, i);
179*37da2899SCharles.Forsyth 	if(a->stipple)
180*37da2899SCharles.Forsyth 		freeimage(a->stipple);
181*37da2899SCharles.Forsyth 	if(a->pen)
182*37da2899SCharles.Forsyth 		freeimage(a->pen);
183*37da2899SCharles.Forsyth }
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth void
tkcvsarcdraw(Image * img,TkCitem * i,TkEnv * pe)186*37da2899SCharles.Forsyth tkcvsarcdraw(Image *img, TkCitem *i, TkEnv *pe)
187*37da2899SCharles.Forsyth {
188*37da2899SCharles.Forsyth 	TkEnv *e;
189*37da2899SCharles.Forsyth 	TkCarc *a;
190*37da2899SCharles.Forsyth 	Rectangle d;
191*37da2899SCharles.Forsyth 	int w, dx, dy;
192*37da2899SCharles.Forsyth 	int s, ext, s0, s1, e0, e1, l;
193*37da2899SCharles.Forsyth 	Image *pen, *col, *tmp;
194*37da2899SCharles.Forsyth 	Point p0, p1, c;
195*37da2899SCharles.Forsyth 	extern void drawarc(Point,int,int,int,int,int,Image *,Image *,Image *);
196*37da2899SCharles.Forsyth 
197*37da2899SCharles.Forsyth 	USED(pe);
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth 	d.min = i->p.drawpt[0];
200*37da2899SCharles.Forsyth 	d.max = i->p.drawpt[1];
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth 	e = i->env;
203*37da2899SCharles.Forsyth 	a = TKobj(TkCarc, i);
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth 	pen = a->pen;
206*37da2899SCharles.Forsyth 	if(pen == nil && (e->set & (1<<TkCfill)))
207*37da2899SCharles.Forsyth 		pen = tkgc(e, TkCfill);
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth 	w = TKF2I(a->width)/2;
210*37da2899SCharles.Forsyth 	if(w < 0)
211*37da2899SCharles.Forsyth 		return;
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth 	d = canonrect(d);
214*37da2899SCharles.Forsyth 	dx = Dx(d)/2;
215*37da2899SCharles.Forsyth 	dy = Dy(d)/2;
216*37da2899SCharles.Forsyth 	c.x = (d.min.x+d.max.x)/2;
217*37da2899SCharles.Forsyth 	c.y = (d.min.y+d.max.y)/2;
218*37da2899SCharles.Forsyth 	s = TKF2I(a->start);
219*37da2899SCharles.Forsyth 	ext = TKF2I(a->extent);
220*37da2899SCharles.Forsyth /*
221*37da2899SCharles.Forsyth 	if(ext == 0)
222*37da2899SCharles.Forsyth 		ext = 90;
223*37da2899SCharles.Forsyth */
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth 	if(a->style != Arc && pen != nil)
226*37da2899SCharles.Forsyth 		fillarc(img, c, dx, dy, pen, Pt(0,0), s, ext);
227*37da2899SCharles.Forsyth 	col = tkgc(e, TkCforegnd);
228*37da2899SCharles.Forsyth 	arc(img, c, dx, dy, w, col, Pt(0,0), s, ext);
229*37da2899SCharles.Forsyth 	if(a->style == Pieslice){
230*37da2899SCharles.Forsyth 		/*
231*37da2899SCharles.Forsyth 		 * It is difficult to compute the intersection of the lines
232*37da2899SCharles.Forsyth 		 * and the ellipse using integers, so let the draw library
233*37da2899SCharles.Forsyth 		 * do it for us: use a full ellipse as the source of color
234*37da2899SCharles.Forsyth 		 * for drawing the lines.
235*37da2899SCharles.Forsyth 		 */
236*37da2899SCharles.Forsyth 		tmp = allocimage(img->display, d, img->chan, 0, DNofill);
237*37da2899SCharles.Forsyth 		if(tmp == nil)
238*37da2899SCharles.Forsyth 			return;
239*37da2899SCharles.Forsyth 		/* copy dest to tmp so lines don't spill beyond edge of ellipse */
240*37da2899SCharles.Forsyth 		drawop(tmp, d, img, nil, d.min, S);
241*37da2899SCharles.Forsyth 		fillellipse(tmp, c, dx, dy, col, Pt(0,0));
242*37da2899SCharles.Forsyth 		icossin(s, &s1, &s0);
243*37da2899SCharles.Forsyth 		icossin(s+ext, &e1, &e0);
244*37da2899SCharles.Forsyth 		if(dx > dy)
245*37da2899SCharles.Forsyth 			l = 2*dx+1;
246*37da2899SCharles.Forsyth 		else
247*37da2899SCharles.Forsyth 			l = 2*dy+1;
248*37da2899SCharles.Forsyth 		p0 = Pt(c.x+l*s1/ICOSSCALE, c.y-l*s0/ICOSSCALE);
249*37da2899SCharles.Forsyth 		p1 = Pt(c.x+l*e1/ICOSSCALE, c.y-l*e0/ICOSSCALE);
250*37da2899SCharles.Forsyth 		line(img, c, p0, Endsquare, Endsquare, w, tmp, c);
251*37da2899SCharles.Forsyth 		line(img, c, p1, Endsquare, Endsquare, w, tmp, c);
252*37da2899SCharles.Forsyth 		freeimage(tmp);
253*37da2899SCharles.Forsyth 	}
254*37da2899SCharles.Forsyth }
255*37da2899SCharles.Forsyth 
256*37da2899SCharles.Forsyth char*
tkcvsarccoord(TkCitem * i,char * arg,int x,int y)257*37da2899SCharles.Forsyth tkcvsarccoord(TkCitem *i, char *arg, int x, int y)
258*37da2899SCharles.Forsyth {
259*37da2899SCharles.Forsyth 	char *e;
260*37da2899SCharles.Forsyth 	TkCpoints p;
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth 	if(arg == nil) {
263*37da2899SCharles.Forsyth 		tkxlatepts(i->p.parampt, i->p.npoint, x, y);
264*37da2899SCharles.Forsyth 		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
265*37da2899SCharles.Forsyth 		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
266*37da2899SCharles.Forsyth 	}
267*37da2899SCharles.Forsyth 	else {
268*37da2899SCharles.Forsyth 		e = tkparsepts(i->env->top, &p, &arg, 0);
269*37da2899SCharles.Forsyth 		if(e != nil)
270*37da2899SCharles.Forsyth 			return e;
271*37da2899SCharles.Forsyth 		if(p.npoint != 2) {
272*37da2899SCharles.Forsyth 			tkfreepoint(&p);
273*37da2899SCharles.Forsyth 			return TkFewpt;
274*37da2899SCharles.Forsyth 		}
275*37da2899SCharles.Forsyth 		tkfreepoint(&i->p);
276*37da2899SCharles.Forsyth 		i->p = p;
277*37da2899SCharles.Forsyth 		tkcvsarcsize(i);
278*37da2899SCharles.Forsyth 	}
279*37da2899SCharles.Forsyth 	return nil;
280*37da2899SCharles.Forsyth }
281