xref: /inferno-os/libtk/cline.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 /* Line Options (+ means implemented)
9*37da2899SCharles.Forsyth 	+arrow
10*37da2899SCharles.Forsyth 	+arrowshape
11*37da2899SCharles.Forsyth 	+capstyle
12*37da2899SCharles.Forsyth 	+fill
13*37da2899SCharles.Forsyth 	 joinstyle
14*37da2899SCharles.Forsyth 	+smooth
15*37da2899SCharles.Forsyth 	+splinesteps
16*37da2899SCharles.Forsyth 	+stipple
17*37da2899SCharles.Forsyth 	+tags
18*37da2899SCharles.Forsyth 	+width
19*37da2899SCharles.Forsyth */
20*37da2899SCharles.Forsyth 
21*37da2899SCharles.Forsyth static
22*37da2899SCharles.Forsyth TkStab tklines[] =
23*37da2899SCharles.Forsyth {
24*37da2899SCharles.Forsyth 	"none",		0,
25*37da2899SCharles.Forsyth 	"first",	TkCarrowf,
26*37da2899SCharles.Forsyth 	"last",		TkCarrowl,
27*37da2899SCharles.Forsyth 	"both",		TkCarrowf|TkCarrowl,
28*37da2899SCharles.Forsyth 	nil
29*37da2899SCharles.Forsyth };
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth static
32*37da2899SCharles.Forsyth TkStab tkcapstyle[] =
33*37da2899SCharles.Forsyth {
34*37da2899SCharles.Forsyth 	"butt",	Endsquare,
35*37da2899SCharles.Forsyth 	"projecting",	Endsquare,
36*37da2899SCharles.Forsyth 	"round",	Enddisc,
37*37da2899SCharles.Forsyth 	nil
38*37da2899SCharles.Forsyth };
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth static
41*37da2899SCharles.Forsyth TkOption lineopts[] =
42*37da2899SCharles.Forsyth {
43*37da2899SCharles.Forsyth 	"arrow",	OPTstab,	O(TkCline, arrow),	tklines,
44*37da2899SCharles.Forsyth 	"arrowshape",	OPTfrac,	O(TkCline, shape[0]),	IAUX(3),
45*37da2899SCharles.Forsyth 	"width",	OPTnnfrac,	O(TkCline, width),	nil,
46*37da2899SCharles.Forsyth 	"stipple",	OPTbmap,	O(TkCline, stipple),	nil,
47*37da2899SCharles.Forsyth 	"smooth",	OPTstab,	O(TkCline, smooth),	tkbool,
48*37da2899SCharles.Forsyth 	"splinesteps",	OPTdist,	O(TkCline, steps),	nil,
49*37da2899SCharles.Forsyth 	"capstyle",	OPTstab,	O(TkCline, capstyle),	tkcapstyle,
50*37da2899SCharles.Forsyth 	nil
51*37da2899SCharles.Forsyth };
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth static
54*37da2899SCharles.Forsyth TkOption itemopts[] =
55*37da2899SCharles.Forsyth {
56*37da2899SCharles.Forsyth 	"tags",		OPTctag,	O(TkCitem, tags),	nil,
57*37da2899SCharles.Forsyth 	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),
58*37da2899SCharles.Forsyth 	nil
59*37da2899SCharles.Forsyth };
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth void
tkcvslinesize(TkCitem * i)62*37da2899SCharles.Forsyth tkcvslinesize(TkCitem *i)
63*37da2899SCharles.Forsyth {
64*37da2899SCharles.Forsyth 	TkCline *l;
65*37da2899SCharles.Forsyth 	int j, w, as, shape[3], arrow;
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth 	l = TKobj(TkCline, i);
68*37da2899SCharles.Forsyth 	w = TKF2I(l->width);
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth 	i->p.bb = bbnil;
71*37da2899SCharles.Forsyth 	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth 	l->arrowf = l->capstyle;
74*37da2899SCharles.Forsyth 	l->arrowl = l->capstyle;
75*37da2899SCharles.Forsyth 	if(l->arrow != 0) {
76*37da2899SCharles.Forsyth 		as = w/3;
77*37da2899SCharles.Forsyth 		if(as < 1)
78*37da2899SCharles.Forsyth 			as = 1;
79*37da2899SCharles.Forsyth 		for(j = 0; j < 3; j++) {
80*37da2899SCharles.Forsyth 			shape[j] = l->shape[j];
81*37da2899SCharles.Forsyth 			if(shape[j] == 0)
82*37da2899SCharles.Forsyth 				shape[j] = as * cvslshape[j];
83*37da2899SCharles.Forsyth 		}
84*37da2899SCharles.Forsyth 		arrow = ARROW(TKF2I(shape[0]), TKF2I(shape[1]), TKF2I(shape[2]));
85*37da2899SCharles.Forsyth 		if(l->arrow & TkCarrowf)
86*37da2899SCharles.Forsyth 			l->arrowf = arrow;
87*37da2899SCharles.Forsyth 		if(l->arrow & TkCarrowl)
88*37da2899SCharles.Forsyth 			l->arrowl = arrow;
89*37da2899SCharles.Forsyth 		w += shape[2];
90*37da2899SCharles.Forsyth 	}
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth 	i->p.bb = insetrect(i->p.bb, -w);
93*37da2899SCharles.Forsyth }
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth char*
tkcvslinecreat(Tk * tk,char * arg,char ** val)96*37da2899SCharles.Forsyth tkcvslinecreat(Tk* tk, char *arg, char **val)
97*37da2899SCharles.Forsyth {
98*37da2899SCharles.Forsyth 	char *e;
99*37da2899SCharles.Forsyth 	TkCline *l;
100*37da2899SCharles.Forsyth 	TkCitem *i;
101*37da2899SCharles.Forsyth 	TkCanvas *c;
102*37da2899SCharles.Forsyth 	TkOptab tko[3];
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth 	i = tkcnewitem(tk, TkCVline, sizeof(TkCitem)+sizeof(TkCline));
107*37da2899SCharles.Forsyth 	if(i == nil)
108*37da2899SCharles.Forsyth 		return TkNomem;
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth 	l = TKobj(TkCline, i);
111*37da2899SCharles.Forsyth 	l->width = TKI2F(1);
112*37da2899SCharles.Forsyth 
113*37da2899SCharles.Forsyth 	e = tkparsepts(tk->env->top, &i->p, &arg, 0);
114*37da2899SCharles.Forsyth 	if(e != nil) {
115*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
116*37da2899SCharles.Forsyth 		return e;
117*37da2899SCharles.Forsyth 	}
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth 	tko[0].ptr = l;
120*37da2899SCharles.Forsyth 	tko[0].optab = lineopts;
121*37da2899SCharles.Forsyth 	tko[1].ptr = i;
122*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
123*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
124*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
125*37da2899SCharles.Forsyth 	if(e != nil) {
126*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
127*37da2899SCharles.Forsyth 		return e;
128*37da2899SCharles.Forsyth 	}
129*37da2899SCharles.Forsyth 	tkmkpen(&l->pen, i->env, l->stipple);
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth 	e = tkcaddtag(tk, i, 1);
132*37da2899SCharles.Forsyth 	if(e != nil) {
133*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
134*37da2899SCharles.Forsyth 		return e;
135*37da2899SCharles.Forsyth 	}
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth 	tkcvslinesize(i);
138*37da2899SCharles.Forsyth 	e = tkvalue(val, "%d", i->id);
139*37da2899SCharles.Forsyth 	if(e != nil) {
140*37da2899SCharles.Forsyth 		tkcvsfreeitem(i);
141*37da2899SCharles.Forsyth 		return e;
142*37da2899SCharles.Forsyth 	}
143*37da2899SCharles.Forsyth 	tkcvsappend(c, i);
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth 	tkbbmax(&c->update, &i->p.bb);
146*37da2899SCharles.Forsyth 	tkcvssetdirty(tk);
147*37da2899SCharles.Forsyth 	return nil;
148*37da2899SCharles.Forsyth }
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth char*
tkcvslinecget(TkCitem * i,char * arg,char ** val)151*37da2899SCharles.Forsyth tkcvslinecget(TkCitem *i, char *arg, char **val)
152*37da2899SCharles.Forsyth {
153*37da2899SCharles.Forsyth 	TkOptab tko[3];
154*37da2899SCharles.Forsyth 	TkCline *l = TKobj(TkCline, i);
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth 	tko[0].ptr = l;
157*37da2899SCharles.Forsyth 	tko[0].optab = lineopts;
158*37da2899SCharles.Forsyth 	tko[1].ptr = i;
159*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
160*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, i->env->top);
163*37da2899SCharles.Forsyth }
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth char*
tkcvslineconf(Tk * tk,TkCitem * i,char * arg)166*37da2899SCharles.Forsyth tkcvslineconf(Tk *tk, TkCitem *i, char *arg)
167*37da2899SCharles.Forsyth {
168*37da2899SCharles.Forsyth 	char *e;
169*37da2899SCharles.Forsyth 	TkOptab tko[3];
170*37da2899SCharles.Forsyth 	TkCline *l = TKobj(TkCline, i);
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth 	tko[0].ptr = l;
173*37da2899SCharles.Forsyth 	tko[0].optab = lineopts;
174*37da2899SCharles.Forsyth 	tko[1].ptr = i;
175*37da2899SCharles.Forsyth 	tko[1].optab = itemopts;
176*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth 	tkmkpen(&l->pen, i->env, l->stipple);
181*37da2899SCharles.Forsyth 	tkcvslinesize(i);
182*37da2899SCharles.Forsyth 
183*37da2899SCharles.Forsyth 	return e;
184*37da2899SCharles.Forsyth }
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth void
tkcvslinefree(TkCitem * i)187*37da2899SCharles.Forsyth tkcvslinefree(TkCitem *i)
188*37da2899SCharles.Forsyth {
189*37da2899SCharles.Forsyth 	TkCline *l;
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth 	l = TKobj(TkCline, i);
192*37da2899SCharles.Forsyth 	if(l->stipple)
193*37da2899SCharles.Forsyth 		freeimage(l->stipple);
194*37da2899SCharles.Forsyth 	if(l->pen)
195*37da2899SCharles.Forsyth 		freeimage(l->pen);
196*37da2899SCharles.Forsyth }
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth void
tkcvslinedraw(Image * img,TkCitem * i,TkEnv * pe)199*37da2899SCharles.Forsyth tkcvslinedraw(Image *img, TkCitem *i, TkEnv *pe)
200*37da2899SCharles.Forsyth {
201*37da2899SCharles.Forsyth 	int w;
202*37da2899SCharles.Forsyth 	Point *p;
203*37da2899SCharles.Forsyth 	TkCline *l;
204*37da2899SCharles.Forsyth 	Image *pen;
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth 	USED(pe);
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth 	l = TKobj(TkCline, i);
209*37da2899SCharles.Forsyth 
210*37da2899SCharles.Forsyth 	pen = l->pen;
211*37da2899SCharles.Forsyth 	if(pen == nil)
212*37da2899SCharles.Forsyth 		pen = tkgc(i->env, TkCforegnd);
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth 	w = TKF2I(l->width)/2;
215*37da2899SCharles.Forsyth 	if(w < 0)
216*37da2899SCharles.Forsyth 		return;
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth 	p = i->p.drawpt;
219*37da2899SCharles.Forsyth 	if(l->smooth == BoolT && i->p.npoint >= 3)
220*37da2899SCharles.Forsyth 		bezspline(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
221*37da2899SCharles.Forsyth 	else
222*37da2899SCharles.Forsyth 		poly(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
223*37da2899SCharles.Forsyth }
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth char*
tkcvslinecoord(TkCitem * i,char * arg,int x,int y)226*37da2899SCharles.Forsyth tkcvslinecoord(TkCitem *i, char *arg, int x, int y)
227*37da2899SCharles.Forsyth {
228*37da2899SCharles.Forsyth 	char *e;
229*37da2899SCharles.Forsyth 	TkCpoints p;
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth 	if(arg == nil) {
232*37da2899SCharles.Forsyth 		tkxlatepts(i->p.parampt, i->p.npoint, x, y);
233*37da2899SCharles.Forsyth 		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
234*37da2899SCharles.Forsyth 		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
235*37da2899SCharles.Forsyth 	}
236*37da2899SCharles.Forsyth 	else {
237*37da2899SCharles.Forsyth 		e = tkparsepts(i->env->top, &p, &arg, 0);
238*37da2899SCharles.Forsyth 		if(e != nil)
239*37da2899SCharles.Forsyth 			return e;
240*37da2899SCharles.Forsyth 		if(p.npoint < 2) {
241*37da2899SCharles.Forsyth 			tkfreepoint(&p);
242*37da2899SCharles.Forsyth 			return TkFewpt;
243*37da2899SCharles.Forsyth 		}
244*37da2899SCharles.Forsyth 		tkfreepoint(&i->p);
245*37da2899SCharles.Forsyth 		i->p = p;
246*37da2899SCharles.Forsyth 		tkcvslinesize(i);
247*37da2899SCharles.Forsyth 	}
248*37da2899SCharles.Forsyth 	return nil;
249*37da2899SCharles.Forsyth }
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth int
tkcvslinehit(TkCitem * i,Point p)252*37da2899SCharles.Forsyth tkcvslinehit(TkCitem *i, Point p)
253*37da2899SCharles.Forsyth {
254*37da2899SCharles.Forsyth 	TkCline *l;
255*37da2899SCharles.Forsyth 	int w, np, r;
256*37da2899SCharles.Forsyth 	Point *pp;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 	l = TKobj(TkCline, i);
259*37da2899SCharles.Forsyth 	w =TKF2I(l->width) + 2;	/* 2 for slop */
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth 	if (l->smooth == BoolT) {
262*37da2899SCharles.Forsyth 		np = getbezsplinepts(i->p.drawpt, i->p.npoint, &pp);
263*37da2899SCharles.Forsyth 		r = tklinehit(pp, np, w, p);
264*37da2899SCharles.Forsyth 		free(pp);
265*37da2899SCharles.Forsyth 	} else
266*37da2899SCharles.Forsyth 		r = tklinehit(i->p.drawpt, i->p.npoint, w, p);
267*37da2899SCharles.Forsyth 	return r;
268*37da2899SCharles.Forsyth }
269