xref: /plan9/sys/src/libdraw/alloc.c (revision 108f07eed5e0376d0a0522a07177896de3f9c625)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier Image*
allocimage(Display * d,Rectangle r,ulong chan,int repl,ulong val)67dd7cddfSDavid du Colombier allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val)
77dd7cddfSDavid du Colombier {
850e5f38dSDavid du Colombier 	Image*	i;
950e5f38dSDavid du Colombier 
1050e5f38dSDavid du Colombier 	i =  _allocimage(nil, d, r, chan, repl, val, 0, 0);
1150e5f38dSDavid du Colombier 	if (i)
1250e5f38dSDavid du Colombier 		setmalloctag(i, getcallerpc(&d));
1350e5f38dSDavid du Colombier 	return i;
147dd7cddfSDavid du Colombier }
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier Image*
_allocimage(Image * ai,Display * d,Rectangle r,ulong chan,int repl,ulong val,int screenid,int refresh)177dd7cddfSDavid du Colombier _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh)
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	uchar *a;
207dd7cddfSDavid du Colombier 	char *err;
217dd7cddfSDavid du Colombier 	Image *i;
227dd7cddfSDavid du Colombier 	Rectangle clipr;
237dd7cddfSDavid du Colombier 	int id;
247dd7cddfSDavid du Colombier 	int depth;
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier 	err = 0;
277dd7cddfSDavid du Colombier 	i = 0;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	if(chan == 0){
307dd7cddfSDavid du Colombier 		werrstr("bad channel descriptor");
317dd7cddfSDavid du Colombier 		return nil;
327dd7cddfSDavid du Colombier 	}
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier 	depth = chantodepth(chan);
357dd7cddfSDavid du Colombier 	if(depth == 0){
367dd7cddfSDavid du Colombier 		err = "bad channel descriptor";
377dd7cddfSDavid du Colombier     Error:
387dd7cddfSDavid du Colombier 		if(err)
397dd7cddfSDavid du Colombier 			werrstr("allocimage: %s", err);
407dd7cddfSDavid du Colombier 		else
417dd7cddfSDavid du Colombier 			werrstr("allocimage: %r");
427dd7cddfSDavid du Colombier 		free(i);
437dd7cddfSDavid du Colombier 		return 0;
447dd7cddfSDavid du Colombier 	}
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier 	/* flush pending data so we don't get error allocating the image */
477dd7cddfSDavid du Colombier 	flushimage(d, 0);
487dd7cddfSDavid du Colombier 	a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
497dd7cddfSDavid du Colombier 	if(a == 0)
507dd7cddfSDavid du Colombier 		goto Error;
517dd7cddfSDavid du Colombier 	d->imageid++;
527dd7cddfSDavid du Colombier 	id = d->imageid;
537dd7cddfSDavid du Colombier 	a[0] = 'b';
547dd7cddfSDavid du Colombier 	BPLONG(a+1, id);
557dd7cddfSDavid du Colombier 	BPLONG(a+5, screenid);
567dd7cddfSDavid du Colombier 	a[9] = refresh;
577dd7cddfSDavid du Colombier 	BPLONG(a+10, chan);
587dd7cddfSDavid du Colombier 	a[14] = repl;
597dd7cddfSDavid du Colombier 	BPLONG(a+15, r.min.x);
607dd7cddfSDavid du Colombier 	BPLONG(a+19, r.min.y);
617dd7cddfSDavid du Colombier 	BPLONG(a+23, r.max.x);
627dd7cddfSDavid du Colombier 	BPLONG(a+27, r.max.y);
637dd7cddfSDavid du Colombier 	if(repl)
647dd7cddfSDavid du Colombier 		/* huge but not infinite, so various offsets will leave it huge, not overflow */
657dd7cddfSDavid du Colombier 		clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
667dd7cddfSDavid du Colombier 	else
677dd7cddfSDavid du Colombier 		clipr = r;
687dd7cddfSDavid du Colombier 	BPLONG(a+31, clipr.min.x);
697dd7cddfSDavid du Colombier 	BPLONG(a+35, clipr.min.y);
707dd7cddfSDavid du Colombier 	BPLONG(a+39, clipr.max.x);
717dd7cddfSDavid du Colombier 	BPLONG(a+43, clipr.max.y);
727dd7cddfSDavid du Colombier 	BPLONG(a+47, val);
737dd7cddfSDavid du Colombier 	if(flushimage(d, 0) < 0)
747dd7cddfSDavid du Colombier 		goto Error;
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	if(ai)
777dd7cddfSDavid du Colombier 		i = ai;
787dd7cddfSDavid du Colombier 	else{
797dd7cddfSDavid du Colombier 		i = malloc(sizeof(Image));
807dd7cddfSDavid du Colombier 		if(i == nil){
817dd7cddfSDavid du Colombier 			a = bufimage(d, 1+4);
827dd7cddfSDavid du Colombier 			if(a){
837dd7cddfSDavid du Colombier 				a[0] = 'f';
847dd7cddfSDavid du Colombier 				BPLONG(a+1, id);
857dd7cddfSDavid du Colombier 				flushimage(d, 0);
867dd7cddfSDavid du Colombier 			}
877dd7cddfSDavid du Colombier 			goto Error;
887dd7cddfSDavid du Colombier 		}
897dd7cddfSDavid du Colombier 	}
907dd7cddfSDavid du Colombier 	i->display = d;
917dd7cddfSDavid du Colombier 	i->id = id;
927dd7cddfSDavid du Colombier 	i->depth = depth;
937dd7cddfSDavid du Colombier 	i->chan = chan;
947dd7cddfSDavid du Colombier 	i->r = r;
957dd7cddfSDavid du Colombier 	i->clipr = clipr;
967dd7cddfSDavid du Colombier 	i->repl = repl;
977dd7cddfSDavid du Colombier 	i->screen = 0;
987dd7cddfSDavid du Colombier 	i->next = 0;
997dd7cddfSDavid du Colombier 	return i;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier Image*
namedimage(Display * d,char * name)1037dd7cddfSDavid du Colombier namedimage(Display *d, char *name)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	uchar *a;
1067dd7cddfSDavid du Colombier 	char *err, buf[12*12+1];
1077dd7cddfSDavid du Colombier 	Image *i;
1087dd7cddfSDavid du Colombier 	int id, n;
1097dd7cddfSDavid du Colombier 	ulong chan;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 	err = 0;
1127dd7cddfSDavid du Colombier 	i = 0;
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier 	n = strlen(name);
1157dd7cddfSDavid du Colombier 	if(n >= 256){
1167dd7cddfSDavid du Colombier 		err = "name too long";
1177dd7cddfSDavid du Colombier     Error:
1187dd7cddfSDavid du Colombier 		if(err)
1197dd7cddfSDavid du Colombier 			werrstr("namedimage: %s", err);
1207dd7cddfSDavid du Colombier 		else
1217dd7cddfSDavid du Colombier 			werrstr("namedimage: %r");
1227dd7cddfSDavid du Colombier 		if(i)
1237dd7cddfSDavid du Colombier 			free(i);
1247dd7cddfSDavid du Colombier 		return 0;
1257dd7cddfSDavid du Colombier 	}
1267dd7cddfSDavid du Colombier 	/* flush pending data so we don't get error allocating the image */
1277dd7cddfSDavid du Colombier 	flushimage(d, 0);
1287dd7cddfSDavid du Colombier 	a = bufimage(d, 1+4+1+n);
1297dd7cddfSDavid du Colombier 	if(a == 0)
1307dd7cddfSDavid du Colombier 		goto Error;
1317dd7cddfSDavid du Colombier 	d->imageid++;
1327dd7cddfSDavid du Colombier 	id = d->imageid;
1337dd7cddfSDavid du Colombier 	a[0] = 'n';
1347dd7cddfSDavid du Colombier 	BPLONG(a+1, id);
1357dd7cddfSDavid du Colombier 	a[5] = n;
1367dd7cddfSDavid du Colombier 	memmove(a+6, name, n);
1377dd7cddfSDavid du Colombier 	if(flushimage(d, 0) < 0)
1387dd7cddfSDavid du Colombier 		goto Error;
1397dd7cddfSDavid du Colombier 
1409a747e4fSDavid du Colombier 	if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
1417dd7cddfSDavid du Colombier 		goto Error;
1429a747e4fSDavid du Colombier 	buf[12*12] = '\0';
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	i = malloc(sizeof(Image));
1457dd7cddfSDavid du Colombier 	if(i == nil){
1467dd7cddfSDavid du Colombier 	Error1:
1477dd7cddfSDavid du Colombier 		a = bufimage(d, 1+4);
1487dd7cddfSDavid du Colombier 		if(a){
1497dd7cddfSDavid du Colombier 			a[0] = 'f';
1507dd7cddfSDavid du Colombier 			BPLONG(a+1, id);
1517dd7cddfSDavid du Colombier 			flushimage(d, 0);
1527dd7cddfSDavid du Colombier 		}
1537dd7cddfSDavid du Colombier 		goto Error;
1547dd7cddfSDavid du Colombier 	}
1557dd7cddfSDavid du Colombier 	i->display = d;
1567dd7cddfSDavid du Colombier 	i->id = id;
1577dd7cddfSDavid du Colombier 	if((chan=strtochan(buf+2*12))==0){
1589a747e4fSDavid du Colombier 		werrstr("bad channel '%.12s' from devdraw", buf+2*12);
1597dd7cddfSDavid du Colombier 		goto Error1;
1607dd7cddfSDavid du Colombier 	}
1617dd7cddfSDavid du Colombier 	i->chan = chan;
1627dd7cddfSDavid du Colombier 	i->depth = chantodepth(chan);
1637dd7cddfSDavid du Colombier 	i->repl = atoi(buf+3*12);
1647dd7cddfSDavid du Colombier 	i->r.min.x = atoi(buf+4*12);
1657dd7cddfSDavid du Colombier 	i->r.min.y = atoi(buf+5*12);
1667dd7cddfSDavid du Colombier 	i->r.max.x = atoi(buf+6*12);
1677dd7cddfSDavid du Colombier 	i->r.max.y = atoi(buf+7*12);
1687dd7cddfSDavid du Colombier 	i->clipr.min.x = atoi(buf+8*12);
1697dd7cddfSDavid du Colombier 	i->clipr.min.y = atoi(buf+9*12);
1707dd7cddfSDavid du Colombier 	i->clipr.max.x = atoi(buf+10*12);
1717dd7cddfSDavid du Colombier 	i->clipr.max.y = atoi(buf+11*12);
1727dd7cddfSDavid du Colombier 	i->screen = 0;
1737dd7cddfSDavid du Colombier 	i->next = 0;
1747dd7cddfSDavid du Colombier 	return i;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier int
nameimage(Image * i,char * name,int in)1787dd7cddfSDavid du Colombier nameimage(Image *i, char *name, int in)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier 	uchar *a;
1817dd7cddfSDavid du Colombier 	int n;
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier 	n = strlen(name);
1847dd7cddfSDavid du Colombier 	a = bufimage(i->display, 1+4+1+1+n);
1857dd7cddfSDavid du Colombier 	if(a == 0)
1867dd7cddfSDavid du Colombier 		return 0;
1877dd7cddfSDavid du Colombier 	a[0] = 'N';
1887dd7cddfSDavid du Colombier 	BPLONG(a+1, i->id);
1897dd7cddfSDavid du Colombier 	a[5] = in;
1907dd7cddfSDavid du Colombier 	a[6] = n;
1917dd7cddfSDavid du Colombier 	memmove(a+7, name, n);
1927dd7cddfSDavid du Colombier 	if(flushimage(i->display, 0) < 0)
1937dd7cddfSDavid du Colombier 		return 0;
1947dd7cddfSDavid du Colombier 	return 1;
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier 
1977dd7cddfSDavid du Colombier int
_freeimage1(Image * i)1987dd7cddfSDavid du Colombier _freeimage1(Image *i)
1997dd7cddfSDavid du Colombier {
2007dd7cddfSDavid du Colombier 	uchar *a;
2017dd7cddfSDavid du Colombier 	Display *d;
2027dd7cddfSDavid du Colombier 	Image *w;
2037dd7cddfSDavid du Colombier 
204*108f07eeSDavid du Colombier 	if(i == 0 || i->display == 0)
2057dd7cddfSDavid du Colombier 		return 0;
2067dd7cddfSDavid du Colombier 	/* make sure no refresh events occur on this if we block in the write */
2077dd7cddfSDavid du Colombier 	d = i->display;
2087dd7cddfSDavid du Colombier 	/* flush pending data so we don't get error deleting the image */
2097dd7cddfSDavid du Colombier 	flushimage(d, 0);
2107dd7cddfSDavid du Colombier 	a = bufimage(d, 1+4);
2117dd7cddfSDavid du Colombier 	if(a == 0)
2127dd7cddfSDavid du Colombier 		return -1;
2137dd7cddfSDavid du Colombier 	a[0] = 'f';
2147dd7cddfSDavid du Colombier 	BPLONG(a+1, i->id);
2157dd7cddfSDavid du Colombier 	if(i->screen){
2167dd7cddfSDavid du Colombier 		w = d->windows;
2177dd7cddfSDavid du Colombier 		if(w == i)
2187dd7cddfSDavid du Colombier 			d->windows = i->next;
2197dd7cddfSDavid du Colombier 		else
2207dd7cddfSDavid du Colombier 			while(w){
2217dd7cddfSDavid du Colombier 				if(w->next == i){
2227dd7cddfSDavid du Colombier 					w->next = i->next;
2237dd7cddfSDavid du Colombier 					break;
2247dd7cddfSDavid du Colombier 				}
2257dd7cddfSDavid du Colombier 				w = w->next;
2267dd7cddfSDavid du Colombier 			}
2277dd7cddfSDavid du Colombier 	}
2287dd7cddfSDavid du Colombier 	if(flushimage(d, i->screen!=0) < 0)
2297dd7cddfSDavid du Colombier 		return -1;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	return 0;
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier int
freeimage(Image * i)2357dd7cddfSDavid du Colombier freeimage(Image *i)
2367dd7cddfSDavid du Colombier {
2377dd7cddfSDavid du Colombier 	int ret;
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier 	ret = _freeimage1(i);
2407dd7cddfSDavid du Colombier 	free(i);
2417dd7cddfSDavid du Colombier 	return ret;
2427dd7cddfSDavid du Colombier }
243