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