xref: /inferno-os/libtk/crect.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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