xref: /inferno-os/libtk/cbits.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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 /* Bitmap Options (+ means implemented)
9 	+anchor
10 	+bitmap
11 */
12 
13 typedef struct TkCbits TkCbits;
14 struct TkCbits
15 {
16 	int	anchor;
17 	Point	anchorp;
18 	Image*	bitmap;
19 };
20 
21 static
22 TkOption bitopts[] =
23 {
24 	"anchor",	OPTstab,	O(TkCbits, anchor),	tkanchor,
25 	"bitmap",	OPTbmap,	O(TkCbits, bitmap),	nil,
26 	nil
27 };
28 
29 static
30 TkOption itemopts[] =
31 {
32 	"tags",		OPTctag,	O(TkCitem, tags),	nil,
33 	"background",	OPTcolr,	O(TkCitem, env),	IAUX(TkCbackgnd),
34 	"foreground",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),
35 	nil
36 };
37 
38 void
tkcvsbitsize(TkCitem * i)39 tkcvsbitsize(TkCitem *i)
40 {
41 	Point o;
42 	int dx, dy;
43 	TkCbits *b;
44 
45 	b = TKobj(TkCbits, i);
46 	i->p.bb = bbnil;
47 	if(b->bitmap == nil)
48 		return;
49 
50 	dx = Dx(b->bitmap->r);
51 	dy = Dy(b->bitmap->r);
52 
53 	o = tkcvsanchor(i->p.drawpt[0], dx, dy, b->anchor);
54 
55 	i->p.bb.min.x = o.x;
56 	i->p.bb.min.y = o.y;
57 	i->p.bb.max.x = o.x + dx;
58 	i->p.bb.max.y = o.y + dy;
59 	b->anchorp = subpt(o, i->p.drawpt[0]);
60 }
61 
62 char*
tkcvsbitcreat(Tk * tk,char * arg,char ** val)63 tkcvsbitcreat(Tk* tk, char *arg, char **val)
64 {
65 	char *e;
66 	TkCbits *b;
67 	TkCitem *i;
68 	TkCanvas *c;
69 	TkOptab tko[3];
70 
71 	c = TKobj(TkCanvas, tk);
72 
73 	i = tkcnewitem(tk, TkCVbitmap, sizeof(TkCitem)+sizeof(TkCbits));
74 	if(i == nil)
75 		return TkNomem;
76 
77 	b = TKobj(TkCbits, i);
78 
79 	e = tkparsepts(tk->env->top, &i->p, &arg, 0);
80 	if(e != nil) {
81 		tkcvsfreeitem(i);
82 		return e;
83 	}
84 	if(i->p.npoint != 1) {
85 		tkcvsfreeitem(i);
86 		return TkFewpt;
87 	}
88 
89 	tko[0].ptr = b;
90 	tko[0].optab = bitopts;
91 	tko[1].ptr = i;
92 	tko[1].optab = itemopts;
93 	tko[2].ptr = nil;
94 	e = tkparse(tk->env->top, arg, tko, nil);
95 	if(e != nil) {
96 		tkcvsfreeitem(i);
97 		return e;
98 	}
99 
100 	e = tkcaddtag(tk, i, 1);
101 	if(e != nil) {
102 		tkcvsfreeitem(i);
103 		return e;
104 	}
105 
106 	tkcvsbitsize(i);
107 	tkcvsappend(c, i);
108 
109 	tkbbmax(&c->update, &i->p.bb);
110 	tkcvssetdirty(tk);
111 	return tkvalue(val, "%d", i->id);
112 }
113 
114 char*
tkcvsbitcget(TkCitem * i,char * arg,char ** val)115 tkcvsbitcget(TkCitem *i, char *arg, char **val)
116 {
117 	TkOptab tko[3];
118 	TkCbits *b = TKobj(TkCbits, i);
119 
120 	tko[0].ptr = b;
121 	tko[0].optab = bitopts;
122 	tko[1].ptr = i;
123 	tko[1].optab = itemopts;
124 	tko[2].ptr = nil;
125 
126 	return tkgencget(tko, arg, val, i->env->top);
127 }
128 
129 char*
tkcvsbitconf(Tk * tk,TkCitem * i,char * arg)130 tkcvsbitconf(Tk *tk, TkCitem *i, char *arg)
131 {
132 	char *e;
133 	TkOptab tko[3];
134 	TkCbits *b = TKobj(TkCbits, i);
135 
136 	tko[0].ptr = b;
137 	tko[0].optab = bitopts;
138 	tko[1].ptr = i;
139 	tko[1].optab = itemopts;
140 	tko[2].ptr = nil;
141 
142 	e = tkparse(tk->env->top, arg, tko, nil);
143 	tkcvsbitsize(i);
144 	return e;
145 }
146 
147 void
tkcvsbitfree(TkCitem * i)148 tkcvsbitfree(TkCitem *i)
149 {
150 	TkCbits *b;
151 
152 	b = TKobj(TkCbits, i);
153 	if(b->bitmap)
154 		freeimage(b->bitmap);
155 }
156 
157 void
tkcvsbitdraw(Image * img,TkCitem * i,TkEnv * pe)158 tkcvsbitdraw(Image *img, TkCitem *i, TkEnv *pe)
159 {
160 	TkEnv *e;
161 	TkCbits *b;
162 	Rectangle r;
163 	Image *bi;
164 
165 	USED(pe);
166 
167 	e = i->env;
168 	b = TKobj(TkCbits, i);
169 
170 	bi = b->bitmap;
171 	if(bi == nil)
172 		return;
173 
174 	r.min = addpt(b->anchorp, i->p.drawpt[0]);
175 	r.max = r.min;
176 	r.max.x += Dx(bi->r);
177 	r.max.y += Dy(bi->r);
178 
179 	if(bi->depth != 1) {
180 		draw(img, r, bi, nil, ZP);
181 		return;
182 	}
183 	gendraw(img, r, tkgc(e, TkCbackgnd), r.min, nil, ZP);
184 	draw(img, r, tkgc(e, TkCforegnd), bi, ZP);
185 }
186 
187 char*
tkcvsbitcoord(TkCitem * i,char * arg,int x,int y)188 tkcvsbitcoord(TkCitem *i, char *arg, int x, int y)
189 {
190 	char *e;
191 	TkCpoints p;
192 
193 	if(arg == nil) {
194 		tkxlatepts(i->p.parampt, i->p.npoint, x, y);
195 		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
196 		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
197 	}
198 	else {
199 		e = tkparsepts(i->env->top, &p, &arg, 0);
200 		if(e != nil)
201 			return e;
202 		if(p.npoint != 1) {
203 			tkfreepoint(&p);
204 			return TkFewpt;
205 		}
206 		tkfreepoint(&i->p);
207 		i->p = p;
208 		tkcvsbitsize(i);
209 	}
210 	return nil;
211 }
212