xref: /plan9/sys/src/cmd/unix/drawterm/libmemdraw/alloc.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include "../lib9.h"
2 
3 #include "../libdraw/draw.h"
4 #include "../libmemdraw/memdraw.h"
5 
6 void
7 memimagemove(void *from, void *to)
8 {
9 	Memdata *md;
10 
11 	md = *(Memdata**)to;
12 	if(md->base != from){
13 		print("compacted data not right: #%p\n", md->base);
14 		abort();
15 	}
16 	md->base = to;
17 
18 	/* if allocmemimage changes this must change too */
19 	md->bdata = (uchar*)&md->base[2];
20 }
21 
22 Memimage*
23 allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X)
24 {
25 	int d;
26 	ulong l;
27 	Memimage *i;
28 
29 	if((d = chantodepth(chan)) == 0) {
30 		werrstr("bad channel descriptor %.8lux", chan);
31 		return nil;
32 	}
33 
34 	l = wordsperline(r, d);
35 
36 	i = mallocz(sizeof(Memimage));
37 	if(i == nil)
38 		return nil;
39 
40 	i->data = md;
41 	i->zero = sizeof(ulong)*l*r.min.y;
42 
43 	if(r.min.x >= 0)
44 		i->zero += (r.min.x*d)/8;
45 	else
46 		i->zero -= (-r.min.x*d+7)/8;
47 	i->zero = -i->zero;
48 	i->width = l;
49 	i->r = r;
50 	i->clipr = r;
51 	i->flags = 0;
52 	i->layer = nil;
53 	i->cmap = memdefcmap;
54 	if(memsetchan(i, chan) < 0){
55 		free(i);
56 		return nil;
57 	}
58 	i->X = X;
59 	return i;
60 }
61 
62 Memimage*
63 _allocmemimage(Rectangle r, ulong chan)
64 {
65 	int d;
66 	ulong l, nw;
67 	Memdata *md;
68 	Memimage *i;
69 
70 	if((d = chantodepth(chan)) == 0) {
71 		werrstr("bad channel descriptor %.8lux", chan);
72 		return nil;
73 	}
74 
75 	l = wordsperline(r, d);
76 	nw = l*Dy(r);
77 	md = malloc(sizeof(Memdata));
78 	if(md == nil)
79 		return nil;
80 
81 	md->ref = 1;
82 	md->base = mallocz((2+nw)*sizeof(ulong));
83 	if(md->base == nil){
84 		free(md);
85 		return nil;
86 	}
87 
88 	md->base[0] = (ulong)md;
89 	md->base[1] = getcallerpc(&r);
90 
91 	/* if this changes, memimagemove must change too */
92 	md->bdata = (uchar*)&md->base[2];
93 
94 	md->allocd = 1;
95 
96 	i = allocmemimaged(r, chan, md, nil);
97 	if(i == nil){
98 		free(md);
99 		return nil;
100 	}
101 	md->imref = i;
102 	return i;
103 }
104 
105 void
106 _freememimage(Memimage *i)
107 {
108 	if(i == nil)
109 		return;
110 	if(i->data->ref-- == 1 && i->data->allocd){
111 		if(i->data->base)
112 			free(i->data->base);
113 		free(i->data);
114 	}
115 	free(i);
116 }
117 
118 /*
119  * Wordaddr is deprecated.
120  */
121 ulong*
122 wordaddr(Memimage *i, Point p)
123 {
124 	return (ulong*) ((ulong)byteaddr(i, p) & ~(sizeof(ulong)-1));
125 }
126 
127 uchar*
128 byteaddr(Memimage *i, Point p)
129 {
130 	uchar *a;
131 
132 	a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
133 
134 	if(i->depth < 8){
135 		/*
136 		 * We need to always round down,
137 		 * but C rounds toward zero.
138 		 */
139 		int np;
140 		np = 8/i->depth;
141 		if(p.x < 0)
142 			return a+(p.x-np+1)/np;
143 		else
144 			return a+p.x/np;
145 	}
146 	else
147 		return a+p.x*(i->depth/8);
148 }
149 
150 void
151 _memfillcolor(Memimage *i, ulong val)
152 {
153 	static Memimage *paint;
154 	uchar *data;
155 
156 	if(paint == nil){
157 		paint = allocmemimage(Rect(0,0,1,1), ARGB32);
158 		if(paint == nil)
159 			return;
160 		paint->clipr = Rect(-0x3FFFFFF,-0x3FFFFFF,0x3FFFFFF,0x3FFFFFF);
161 		paint->flags |= Frepl;
162 	}
163 
164 	data = byteaddr(paint, Pt(0,0));
165 	data[0] = val>>8;	/* blue */
166 	data[1] = val>>16;	/* green */
167 	data[2] = val>>24;	/* red */
168 	data[3] = val;		/* alpha */
169 
170 	memimagedraw(i, i->r, paint, ZP, nil, ZP);
171 }
172 
173 int
174 memsetchan(Memimage *i, ulong chan)
175 {
176 	int d;
177 	int t, j, k;
178 	ulong cc;
179 	int bytes;
180 
181 	assert(i->X == nil);
182 	if((d = chantodepth(chan)) == 0) {
183 		werrstr("bad channel descriptor");
184 		return -1;
185 	}
186 
187 	i->depth = d;
188 	i->chan = chan;
189 	i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
190 	bytes = 1;
191 	for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
192 		t=TYPE(cc);
193 		if(t < 0 || t >= NChan){
194 			werrstr("bad channel string");
195 			return -1;
196 		}
197 		if(t == CGrey)
198 			i->flags |= Fgrey;
199 		if(t == CAlpha)
200 			i->flags |= Falpha;
201 		if(t == CMap && i->cmap == nil){
202 			i->cmap = memdefcmap;
203 			i->flags |= Fcmap;
204 		}
205 
206 		i->shift[t] = j;
207 		i->mask[t] = (1<<NBITS(cc))-1;
208 		i->nbits[t] = NBITS(cc);
209 		if(NBITS(cc) != 8)
210 			bytes = 0;
211 	}
212 	i->nchan = k;
213 	if(bytes)
214 		i->flags |= Fbytes;
215 	return 0;
216 }
217