xref: /inferno-os/libdraw/loadimage.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1  #include "lib9.h"
2  #include "draw.h"
3  #include "kernel.h"
4  
5  int
6  loadimage(Image *i, Rectangle r, uchar *data, int ndata)
7  {
8  	long dy;
9  	int n, bpl, roff, dstroff, lskip, llen, y;
10  	uchar *a;
11  	int chunk;
12  	Rectangle dstr;
13  
14  	chunk = i->display->bufsize - 64;
15  
16  	bpl = bytesperline(r, i->depth);
17  	n = bpl*Dy(r);
18  	if(n > ndata){
19  		kwerrstr("loadimage: insufficient data");
20  		return -1;
21  	}
22  
23  	dstr = r;
24  	rectclip(&dstr, i->r);
25  	rectclip(&dstr, i->clipr);
26  
27  	if (!rectinrect(dstr, i->r))
28  		return 0;
29  
30  	roff = (r.min.x*i->depth)>>3;
31  	dstroff = dstr.min.x * i->depth >> 3;
32  	lskip = dstroff - roff;
33  	llen = (dstr.max.x*i->depth + 7 >> 3) - dstroff;
34  	data += (dstr.min.y - r.min.y) * bpl + lskip;
35  
36  	ndata = 0;
37  	while(dstr.max.y > dstr.min.y){
38  		dy = dstr.max.y - dstr.min.y;
39  		if(dy*llen > chunk)
40  			dy = chunk/llen;
41  		if(dy <= 0){
42  			kwerrstr("loadimage: image too wide for buffer");
43  			return -1;
44  		}
45  		n = dy*llen;
46  		a = bufimage(i->display, 21+n);
47  		if(a == nil){
48  			kwerrstr("bufimage failed");
49  			return -1;
50  		}
51  		a[0] = 'y';
52  		BPLONG(a+1, i->id);
53  		BPLONG(a+5, dstr.min.x);
54  		BPLONG(a+9, dstr.min.y);
55  		BPLONG(a+13, dstr.max.x);
56  		BPLONG(a+17, dstr.min.y+dy);
57  		a += 21;
58  		for (y = 0; y < dy; y++) {
59  			memmove(a, data, llen);
60  			a += llen;
61  			ndata += llen;
62  			data += bpl;
63  		}
64  		dstr.min.y += dy;
65  	}
66  	if(flushimage(i->display, 0) < 0)
67  		return -1;
68  	return ndata;
69  }
70  
71