2016-11-25 17:18:40 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
|
|
* in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <draw.h>
|
|
|
|
|
|
|
|
Image*
|
|
|
|
allocimage(Display *d, Rectangle r, uint32_t chan, int repl, uint32_t val)
|
|
|
|
{
|
|
|
|
Image* i;
|
|
|
|
|
|
|
|
i = _allocimage(nil, d, r, chan, repl, val, 0, 0);
|
|
|
|
if (i)
|
|
|
|
setmalloctag(i, getcallerpc());
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
Image*
|
|
|
|
_allocimage(Image *ai, Display *d, Rectangle r, uint32_t chan, int repl,
|
|
|
|
uint32_t val, int screenid, int refresh)
|
|
|
|
{
|
|
|
|
uint8_t *a;
|
|
|
|
char *err;
|
|
|
|
Image *i;
|
|
|
|
Rectangle clipr;
|
|
|
|
int id;
|
|
|
|
int depth;
|
|
|
|
|
|
|
|
err = 0;
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
if(chan == 0){
|
|
|
|
werrstr("bad channel descriptor");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
depth = chantodepth(chan);
|
|
|
|
if(depth == 0){
|
|
|
|
err = "bad channel descriptor";
|
|
|
|
Error:
|
|
|
|
if(err)
|
|
|
|
werrstr("allocimage: %s", err);
|
|
|
|
else
|
|
|
|
werrstr("allocimage: %r");
|
|
|
|
free(i);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* flush pending data so we don't get error allocating the image */
|
|
|
|
flushimage(d, 0);
|
|
|
|
a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
|
|
|
|
if(a == 0)
|
|
|
|
goto Error;
|
|
|
|
d->imageid++;
|
|
|
|
id = d->imageid;
|
|
|
|
a[0] = 'b';
|
|
|
|
BPLONG(a+1, id);
|
|
|
|
BPLONG(a+5, screenid);
|
|
|
|
a[9] = refresh;
|
|
|
|
BPLONG(a+10, chan);
|
|
|
|
a[14] = repl;
|
|
|
|
BPLONG(a+15, r.min.x);
|
|
|
|
BPLONG(a+19, r.min.y);
|
|
|
|
BPLONG(a+23, r.max.x);
|
|
|
|
BPLONG(a+27, r.max.y);
|
|
|
|
if(repl)
|
|
|
|
/* huge but not infinite, so various offsets will leave it huge, not overflow */
|
|
|
|
clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
|
|
|
|
else
|
|
|
|
clipr = r;
|
|
|
|
BPLONG(a+31, clipr.min.x);
|
|
|
|
BPLONG(a+35, clipr.min.y);
|
|
|
|
BPLONG(a+39, clipr.max.x);
|
|
|
|
BPLONG(a+43, clipr.max.y);
|
|
|
|
BPLONG(a+47, val);
|
|
|
|
if(flushimage(d, 0) < 0)
|
|
|
|
goto Error;
|
|
|
|
|
|
|
|
if(ai)
|
|
|
|
i = ai;
|
|
|
|
else{
|
|
|
|
i = malloc(sizeof(Image));
|
|
|
|
if(i == nil){
|
|
|
|
a = bufimage(d, 1+4);
|
|
|
|
if(a){
|
|
|
|
a[0] = 'f';
|
|
|
|
BPLONG(a+1, id);
|
|
|
|
flushimage(d, 0);
|
|
|
|
}
|
|
|
|
goto Error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i->display = d;
|
|
|
|
i->id = id;
|
|
|
|
i->depth = depth;
|
|
|
|
i->chan = chan;
|
|
|
|
i->r = r;
|
|
|
|
i->clipr = clipr;
|
|
|
|
i->repl = repl;
|
|
|
|
i->screen = 0;
|
|
|
|
i->next = 0;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nameimage(Image *i, char *name, int in)
|
|
|
|
{
|
|
|
|
uint8_t *a;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = strlen(name);
|
|
|
|
a = bufimage(i->display, 1+4+1+1+n);
|
|
|
|
if(a == 0)
|
|
|
|
return 0;
|
|
|
|
a[0] = 'N';
|
|
|
|
BPLONG(a+1, i->id);
|
|
|
|
a[5] = in;
|
|
|
|
a[6] = n;
|
|
|
|
memmove(a+7, name, n);
|
|
|
|
if(flushimage(i->display, 0) < 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
_freeimage1(Image *i)
|
|
|
|
{
|
|
|
|
uint8_t *a;
|
|
|
|
Display *d;
|
|
|
|
Image *w;
|
|
|
|
|
|
|
|
if(i == 0 || i->display == 0)
|
|
|
|
return 0;
|
|
|
|
/* make sure no refresh events occur on this if we block in the write */
|
|
|
|
d = i->display;
|
|
|
|
/* flush pending data so we don't get error deleting the image */
|
|
|
|
flushimage(d, 0);
|
|
|
|
a = bufimage(d, 1+4);
|
|
|
|
if(a == 0)
|
|
|
|
return -1;
|
|
|
|
a[0] = 'f';
|
|
|
|
BPLONG(a+1, i->id);
|
|
|
|
if(i->screen){
|
|
|
|
w = d->windows;
|
|
|
|
if(w == i)
|
|
|
|
d->windows = i->next;
|
|
|
|
else
|
|
|
|
while(w){
|
|
|
|
if(w->next == i){
|
|
|
|
w->next = i->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
w = w->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(flushimage(d, i->screen!=0) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
freeimage(Image *i)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = _freeimage1(i);
|
|
|
|
free(i);
|
|
|
|
return ret;
|
|
|
|
}
|