1 #include <lib9.h>
2 #include <kernel.h>
3 #include "draw.h"
4 #include "tk.h"
5 #include "canvs.h"
6
7 #define O(t, e) ((long)(&((t*)0)->e))
8
9 /* Rectangle Options (+ means implemented)
10 +fill
11 +outline
12 +stipple
13 +tags
14 +width
15 */
16
17 typedef struct TkCrect TkCrect;
18 struct TkCrect
19 {
20 int width;
21 Image* stipple;
22 };
23
24 static
25 TkOption rectopts[] =
26 {
27 "width", OPTnnfrac, O(TkCrect, width), nil,
28 "stipple", OPTbmap, O(TkCrect, stipple), nil,
29 nil
30 };
31
32 static
33 TkOption itemopts[] =
34 {
35 "tags", OPTctag, O(TkCitem, tags), nil,
36 "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill),
37 "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd),
38 nil
39 };
40
41 void
tkcvsrectsize(TkCitem * i)42 tkcvsrectsize(TkCitem *i)
43 {
44 TkCrect *r;
45 int w;
46
47 r = TKobj(TkCrect, i);
48 w = TKF2I(r->width)*2;
49
50 i->p.bb = bbnil;
51 tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
52 i->p.bb = insetrect(i->p.bb, -w);
53 }
54
55 static void
tkmkstipple(Image * stipple)56 tkmkstipple(Image *stipple)
57 {
58 int locked;
59 if (stipple != nil && !stipple->repl) {
60 locked = lockdisplay(stipple->display);
61 replclipr(stipple, 1, huger);
62 if (locked)
63 unlockdisplay(stipple->display);
64 }
65 }
66
67 char*
tkcvsrectcreat(Tk * tk,char * arg,char ** val)68 tkcvsrectcreat(Tk* tk, char *arg, char **val)
69 {
70 char *e;
71 TkCrect *r;
72 TkCitem *i;
73 TkCanvas *c;
74 TkOptab tko[3];
75
76 c = TKobj(TkCanvas, tk);
77
78 i = tkcnewitem(tk, TkCVrect, sizeof(TkCitem)+sizeof(TkCrect));
79 if(i == nil)
80 return TkNomem;
81
82 r = TKobj(TkCrect, i);
83 r->width = TKI2F(1);
84
85 e = tkparsepts(tk->env->top, &i->p, &arg, 0);
86 if(e != nil) {
87 tkcvsfreeitem(i);
88 return e;
89 }
90 if(i->p.npoint != 2) {
91 tkcvsfreeitem(i);
92 return TkFewpt;
93 }
94
95 tko[0].ptr = r;
96 tko[0].optab = rectopts;
97 tko[1].ptr = i;
98 tko[1].optab = itemopts;
99 tko[2].ptr = nil;
100 e = tkparse(tk->env->top, arg, tko, nil);
101 if(e != nil) {
102 tkcvsfreeitem(i);
103 return e;
104 }
105 tkmkstipple(r->stipple);
106 e = tkcaddtag(tk, i, 1);
107 if(e != nil) {
108 tkcvsfreeitem(i);
109 return e;
110 }
111
112 tkcvsrectsize(i);
113 e = tkvalue(val, "%d", i->id);
114 if(e != nil) {
115 tkcvsfreeitem(i);
116 return e;
117 }
118 tkcvsappend(c, i);
119
120 tkbbmax(&c->update, &i->p.bb);
121 tkcvssetdirty(tk);
122 return nil;
123 }
124
125 char*
tkcvsrectcget(TkCitem * i,char * arg,char ** val)126 tkcvsrectcget(TkCitem *i, char *arg, char **val)
127 {
128 TkOptab tko[3];
129 TkCrect *r = TKobj(TkCrect, i);
130
131 tko[0].ptr = r;
132 tko[0].optab = rectopts;
133 tko[1].ptr = i;
134 tko[1].optab = itemopts;
135 tko[2].ptr = nil;
136
137 return tkgencget(tko, arg, val, i->env->top);
138 }
139
140 char*
tkcvsrectconf(Tk * tk,TkCitem * i,char * arg)141 tkcvsrectconf(Tk *tk, TkCitem *i, char *arg)
142 {
143 char *e;
144 TkOptab tko[3];
145 TkCrect *r = TKobj(TkCrect, i);
146
147 tko[0].ptr = r;
148 tko[0].optab = rectopts;
149 tko[1].ptr = i;
150 tko[1].optab = itemopts;
151 tko[2].ptr = nil;
152
153 e = tkparse(tk->env->top, arg, tko, nil);
154 tkcvsrectsize(i);
155 tkmkstipple(r->stipple);
156 return e;
157 }
158
159 void
tkcvsrectfree(TkCitem * i)160 tkcvsrectfree(TkCitem *i)
161 {
162 TkCrect *r;
163
164 r = TKobj(TkCrect, i);
165 if(r->stipple)
166 freeimage(r->stipple);
167 }
168
169 void
tkcvsrectdraw(Image * img,TkCitem * i,TkEnv * pe)170 tkcvsrectdraw(Image *img, TkCitem *i, TkEnv *pe)
171 {
172 int lw, rw;
173 TkEnv *e;
174 TkCrect *r;
175 Rectangle d, rr;
176 Point tr, bl;
177 Image *pen;
178
179 USED(pe);
180
181 d.min = i->p.drawpt[0];
182 d.max = i->p.drawpt[1];
183
184 e = i->env;
185 r = TKobj(TkCrect, i);
186
187 pen = nil;
188 if((e->set & (1<<TkCfill)))
189 pen = tkgc(e, TkCfill);
190
191 if(pen != nil)
192 draw(img, d, pen, r->stipple, d.min);
193
194 tr.x = d.max.x;
195 tr.y = d.min.y;
196 bl.x = d.min.x;
197 bl.y = d.max.y;
198
199 rw = (TKF2I(r->width) + 1)/2;
200 if(rw <= 0)
201 return;
202 lw = (TKF2I(r->width))/2;
203
204 pen = tkgc(e, TkCforegnd);
205 if(pen != nil) {
206 /* horizontal lines first */
207 rr.min.x = d.min.x - lw;
208 rr.max.x = d.max.x + rw;
209 rr.min.y = d.min.y - lw;
210 rr.max.y = d.min.y + rw;
211 draw(img, rr, pen, nil, rr.min);
212 rr.min.y += Dy(d);
213 rr.max.y += Dy(d);
214 draw(img, rr, pen, nil, rr.min);
215 /* now the vertical */
216 /* horizontal lines first */
217 rr.min.x = d.min.x - lw;
218 rr.max.x = d.min.x + rw;
219 rr.min.y = d.min.y + rw;
220 rr.max.y = d.max.y - lw;
221 draw(img, rr, pen, nil, rr.min);
222 rr.min.x += Dx(d);
223 rr.max.x += Dx(d);
224 draw(img, rr, pen, nil, rr.min);
225 }
226 }
227
228 char*
tkcvsrectcoord(TkCitem * i,char * arg,int x,int y)229 tkcvsrectcoord(TkCitem *i, char *arg, int x, int y)
230 {
231 char *e;
232 TkCpoints p;
233
234 if(arg == nil) {
235 tkxlatepts(i->p.parampt, i->p.npoint, x, y);
236 tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
237 i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
238 }
239 else {
240 e = tkparsepts(i->env->top, &p, &arg, 0);
241 if(e != nil)
242 return e;
243 if(p.npoint != 2) {
244 tkfreepoint(&p);
245 return TkFewpt;
246 }
247 tkfreepoint(&i->p);
248 i->p = p;
249 tkcvsrectsize(i);
250 }
251 return nil;
252 }
253