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