xref: /plan9/sys/src/libdraw/alloc.c (revision 108f07eed5e0376d0a0522a07177896de3f9c625)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 
5 Image*
allocimage(Display * d,Rectangle r,ulong chan,int repl,ulong val)6 allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val)
7 {
8 	Image*	i;
9 
10 	i =  _allocimage(nil, d, r, chan, repl, val, 0, 0);
11 	if (i)
12 		setmalloctag(i, getcallerpc(&d));
13 	return i;
14 }
15 
16 Image*
_allocimage(Image * ai,Display * d,Rectangle r,ulong chan,int repl,ulong val,int screenid,int refresh)17 _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh)
18 {
19 	uchar *a;
20 	char *err;
21 	Image *i;
22 	Rectangle clipr;
23 	int id;
24 	int depth;
25 
26 	err = 0;
27 	i = 0;
28 
29 	if(chan == 0){
30 		werrstr("bad channel descriptor");
31 		return nil;
32 	}
33 
34 	depth = chantodepth(chan);
35 	if(depth == 0){
36 		err = "bad channel descriptor";
37     Error:
38 		if(err)
39 			werrstr("allocimage: %s", err);
40 		else
41 			werrstr("allocimage: %r");
42 		free(i);
43 		return 0;
44 	}
45 
46 	/* flush pending data so we don't get error allocating the image */
47 	flushimage(d, 0);
48 	a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
49 	if(a == 0)
50 		goto Error;
51 	d->imageid++;
52 	id = d->imageid;
53 	a[0] = 'b';
54 	BPLONG(a+1, id);
55 	BPLONG(a+5, screenid);
56 	a[9] = refresh;
57 	BPLONG(a+10, chan);
58 	a[14] = repl;
59 	BPLONG(a+15, r.min.x);
60 	BPLONG(a+19, r.min.y);
61 	BPLONG(a+23, r.max.x);
62 	BPLONG(a+27, r.max.y);
63 	if(repl)
64 		/* huge but not infinite, so various offsets will leave it huge, not overflow */
65 		clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
66 	else
67 		clipr = r;
68 	BPLONG(a+31, clipr.min.x);
69 	BPLONG(a+35, clipr.min.y);
70 	BPLONG(a+39, clipr.max.x);
71 	BPLONG(a+43, clipr.max.y);
72 	BPLONG(a+47, val);
73 	if(flushimage(d, 0) < 0)
74 		goto Error;
75 
76 	if(ai)
77 		i = ai;
78 	else{
79 		i = malloc(sizeof(Image));
80 		if(i == nil){
81 			a = bufimage(d, 1+4);
82 			if(a){
83 				a[0] = 'f';
84 				BPLONG(a+1, id);
85 				flushimage(d, 0);
86 			}
87 			goto Error;
88 		}
89 	}
90 	i->display = d;
91 	i->id = id;
92 	i->depth = depth;
93 	i->chan = chan;
94 	i->r = r;
95 	i->clipr = clipr;
96 	i->repl = repl;
97 	i->screen = 0;
98 	i->next = 0;
99 	return i;
100 }
101 
102 Image*
namedimage(Display * d,char * name)103 namedimage(Display *d, char *name)
104 {
105 	uchar *a;
106 	char *err, buf[12*12+1];
107 	Image *i;
108 	int id, n;
109 	ulong chan;
110 
111 	err = 0;
112 	i = 0;
113 
114 	n = strlen(name);
115 	if(n >= 256){
116 		err = "name too long";
117     Error:
118 		if(err)
119 			werrstr("namedimage: %s", err);
120 		else
121 			werrstr("namedimage: %r");
122 		if(i)
123 			free(i);
124 		return 0;
125 	}
126 	/* flush pending data so we don't get error allocating the image */
127 	flushimage(d, 0);
128 	a = bufimage(d, 1+4+1+n);
129 	if(a == 0)
130 		goto Error;
131 	d->imageid++;
132 	id = d->imageid;
133 	a[0] = 'n';
134 	BPLONG(a+1, id);
135 	a[5] = n;
136 	memmove(a+6, name, n);
137 	if(flushimage(d, 0) < 0)
138 		goto Error;
139 
140 	if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
141 		goto Error;
142 	buf[12*12] = '\0';
143 
144 	i = malloc(sizeof(Image));
145 	if(i == nil){
146 	Error1:
147 		a = bufimage(d, 1+4);
148 		if(a){
149 			a[0] = 'f';
150 			BPLONG(a+1, id);
151 			flushimage(d, 0);
152 		}
153 		goto Error;
154 	}
155 	i->display = d;
156 	i->id = id;
157 	if((chan=strtochan(buf+2*12))==0){
158 		werrstr("bad channel '%.12s' from devdraw", buf+2*12);
159 		goto Error1;
160 	}
161 	i->chan = chan;
162 	i->depth = chantodepth(chan);
163 	i->repl = atoi(buf+3*12);
164 	i->r.min.x = atoi(buf+4*12);
165 	i->r.min.y = atoi(buf+5*12);
166 	i->r.max.x = atoi(buf+6*12);
167 	i->r.max.y = atoi(buf+7*12);
168 	i->clipr.min.x = atoi(buf+8*12);
169 	i->clipr.min.y = atoi(buf+9*12);
170 	i->clipr.max.x = atoi(buf+10*12);
171 	i->clipr.max.y = atoi(buf+11*12);
172 	i->screen = 0;
173 	i->next = 0;
174 	return i;
175 }
176 
177 int
nameimage(Image * i,char * name,int in)178 nameimage(Image *i, char *name, int in)
179 {
180 	uchar *a;
181 	int n;
182 
183 	n = strlen(name);
184 	a = bufimage(i->display, 1+4+1+1+n);
185 	if(a == 0)
186 		return 0;
187 	a[0] = 'N';
188 	BPLONG(a+1, i->id);
189 	a[5] = in;
190 	a[6] = n;
191 	memmove(a+7, name, n);
192 	if(flushimage(i->display, 0) < 0)
193 		return 0;
194 	return 1;
195 }
196 
197 int
_freeimage1(Image * i)198 _freeimage1(Image *i)
199 {
200 	uchar *a;
201 	Display *d;
202 	Image *w;
203 
204 	if(i == 0 || i->display == 0)
205 		return 0;
206 	/* make sure no refresh events occur on this if we block in the write */
207 	d = i->display;
208 	/* flush pending data so we don't get error deleting the image */
209 	flushimage(d, 0);
210 	a = bufimage(d, 1+4);
211 	if(a == 0)
212 		return -1;
213 	a[0] = 'f';
214 	BPLONG(a+1, i->id);
215 	if(i->screen){
216 		w = d->windows;
217 		if(w == i)
218 			d->windows = i->next;
219 		else
220 			while(w){
221 				if(w->next == i){
222 					w->next = i->next;
223 					break;
224 				}
225 				w = w->next;
226 			}
227 	}
228 	if(flushimage(d, i->screen!=0) < 0)
229 		return -1;
230 
231 	return 0;
232 }
233 
234 int
freeimage(Image * i)235 freeimage(Image *i)
236 {
237 	int ret;
238 
239 	ret = _freeimage1(i);
240 	free(i);
241 	return ret;
242 }
243