Blame


1 76193d7c 2003-09-30 devnull #include <u.h>
2 76193d7c 2003-09-30 devnull #include <libc.h>
3 76193d7c 2003-09-30 devnull #include <bio.h>
4 76193d7c 2003-09-30 devnull #include <draw.h>
5 76193d7c 2003-09-30 devnull #include <memdraw.h>
6 76193d7c 2003-09-30 devnull
7 76193d7c 2003-09-30 devnull #define DBG if(0)
8 76193d7c 2003-09-30 devnull #define RGB2K(r,g,b) ((299*((u32int)(r))+587*((u32int)(g))+114*((u32int)(b)))/1000)
9 76193d7c 2003-09-30 devnull
10 76193d7c 2003-09-30 devnull /*
11 76193d7c 2003-09-30 devnull * This program tests the 'memimagedraw' primitive stochastically.
12 76193d7c 2003-09-30 devnull * It tests the combination aspects of it thoroughly, but since the
13 76193d7c 2003-09-30 devnull * three images it uses are disjoint, it makes no check of the
14 76193d7c 2003-09-30 devnull * correct behavior when images overlap. That is, however, much
15 76193d7c 2003-09-30 devnull * easier to get right and to test.
16 76193d7c 2003-09-30 devnull */
17 76193d7c 2003-09-30 devnull
18 76193d7c 2003-09-30 devnull void drawonepixel(Memimage*, Point, Memimage*, Point, Memimage*, Point);
19 76193d7c 2003-09-30 devnull void verifyone(void);
20 76193d7c 2003-09-30 devnull void verifyline(void);
21 76193d7c 2003-09-30 devnull void verifyrect(void);
22 76193d7c 2003-09-30 devnull void verifyrectrepl(int, int);
23 76193d7c 2003-09-30 devnull void putpixel(Memimage *img, Point pt, u32int nv);
24 76193d7c 2003-09-30 devnull u32int rgbatopix(uchar, uchar, uchar, uchar);
25 76193d7c 2003-09-30 devnull
26 76193d7c 2003-09-30 devnull char *dchan, *schan, *mchan;
27 76193d7c 2003-09-30 devnull int dbpp, sbpp, mbpp;
28 76193d7c 2003-09-30 devnull
29 76193d7c 2003-09-30 devnull int drawdebug=0;
30 76193d7c 2003-09-30 devnull int seed;
31 76193d7c 2003-09-30 devnull int niters = 100;
32 76193d7c 2003-09-30 devnull int dbpp; /* bits per pixel in destination */
33 76193d7c 2003-09-30 devnull int sbpp; /* bits per pixel in src */
34 76193d7c 2003-09-30 devnull int mbpp; /* bits per pixel in mask */
35 76193d7c 2003-09-30 devnull int dpm; /* pixel mask at high part of byte, in destination */
36 76193d7c 2003-09-30 devnull int nbytes; /* in destination */
37 76193d7c 2003-09-30 devnull
38 76193d7c 2003-09-30 devnull int Xrange = 64;
39 76193d7c 2003-09-30 devnull int Yrange = 8;
40 76193d7c 2003-09-30 devnull
41 76193d7c 2003-09-30 devnull Memimage *dst;
42 76193d7c 2003-09-30 devnull Memimage *src;
43 76193d7c 2003-09-30 devnull Memimage *mask;
44 76193d7c 2003-09-30 devnull Memimage *stmp;
45 76193d7c 2003-09-30 devnull Memimage *mtmp;
46 76193d7c 2003-09-30 devnull Memimage *ones;
47 76193d7c 2003-09-30 devnull uchar *dstbits;
48 76193d7c 2003-09-30 devnull uchar *srcbits;
49 76193d7c 2003-09-30 devnull uchar *maskbits;
50 76193d7c 2003-09-30 devnull u32int *savedstbits;
51 76193d7c 2003-09-30 devnull
52 76193d7c 2003-09-30 devnull void
53 76193d7c 2003-09-30 devnull rdb(void)
54 76193d7c 2003-09-30 devnull {
55 76193d7c 2003-09-30 devnull }
56 76193d7c 2003-09-30 devnull
57 76193d7c 2003-09-30 devnull int
58 76193d7c 2003-09-30 devnull iprint(char *fmt, ...)
59 76193d7c 2003-09-30 devnull {
60 76193d7c 2003-09-30 devnull int n;
61 76193d7c 2003-09-30 devnull va_list va;
62 76193d7c 2003-09-30 devnull char buf[1024];
63 76193d7c 2003-09-30 devnull
64 76193d7c 2003-09-30 devnull va_start(va, fmt);
65 76193d7c 2003-09-30 devnull n = doprint(buf, buf+sizeof buf, fmt, va) - buf;
66 76193d7c 2003-09-30 devnull va_end(va);
67 76193d7c 2003-09-30 devnull
68 76193d7c 2003-09-30 devnull write(1,buf,n);
69 76193d7c 2003-09-30 devnull return 1;
70 76193d7c 2003-09-30 devnull }
71 76193d7c 2003-09-30 devnull
72 76193d7c 2003-09-30 devnull void
73 76193d7c 2003-09-30 devnull main(int argc, char *argv[])
74 76193d7c 2003-09-30 devnull {
75 76193d7c 2003-09-30 devnull memimageinit();
76 76193d7c 2003-09-30 devnull seed = time(0);
77 76193d7c 2003-09-30 devnull
78 76193d7c 2003-09-30 devnull ARGBEGIN{
79 76193d7c 2003-09-30 devnull case 'x':
80 76193d7c 2003-09-30 devnull Xrange = atoi(ARGF());
81 76193d7c 2003-09-30 devnull break;
82 76193d7c 2003-09-30 devnull case 'y':
83 76193d7c 2003-09-30 devnull Yrange = atoi(ARGF());
84 76193d7c 2003-09-30 devnull break;
85 76193d7c 2003-09-30 devnull case 'n':
86 76193d7c 2003-09-30 devnull niters = atoi(ARGF());
87 76193d7c 2003-09-30 devnull break;
88 76193d7c 2003-09-30 devnull case 's':
89 76193d7c 2003-09-30 devnull seed = atoi(ARGF());
90 76193d7c 2003-09-30 devnull break;
91 76193d7c 2003-09-30 devnull }ARGEND
92 76193d7c 2003-09-30 devnull
93 76193d7c 2003-09-30 devnull dchan = "r8g8b8";
94 76193d7c 2003-09-30 devnull schan = "r8g8b8";
95 76193d7c 2003-09-30 devnull mchan = "r8g8b8";
96 76193d7c 2003-09-30 devnull switch(argc){
97 76193d7c 2003-09-30 devnull case 3: mchan = argv[2];
98 76193d7c 2003-09-30 devnull case 2: schan = argv[1];
99 76193d7c 2003-09-30 devnull case 1: dchan = argv[0];
100 76193d7c 2003-09-30 devnull case 0: break;
101 76193d7c 2003-09-30 devnull default: goto Usage;
102 76193d7c 2003-09-30 devnull Usage:
103 76193d7c 2003-09-30 devnull fprint(2, "usage: dtest [dchan [schan [mchan]]]\n");
104 76193d7c 2003-09-30 devnull exits("usage");
105 76193d7c 2003-09-30 devnull }
106 76193d7c 2003-09-30 devnull
107 76193d7c 2003-09-30 devnull fmtinstall('b', numbconv); /* binary! */
108 76193d7c 2003-09-30 devnull
109 76193d7c 2003-09-30 devnull fprint(2, "%s -x %d -y %d -s 0x%x %s %s %s\n", argv0, Xrange, Yrange, seed, dchan, schan, mchan);
110 76193d7c 2003-09-30 devnull srand(seed);
111 76193d7c 2003-09-30 devnull
112 76193d7c 2003-09-30 devnull dst = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(dchan));
113 76193d7c 2003-09-30 devnull src = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan));
114 76193d7c 2003-09-30 devnull mask = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
115 76193d7c 2003-09-30 devnull stmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan));
116 76193d7c 2003-09-30 devnull mtmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
117 76193d7c 2003-09-30 devnull ones = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
118 76193d7c 2003-09-30 devnull // print("chan %lux %lux %lux %lux %lux %lux\n", dst->chan, src->chan, mask->chan, stmp->chan, mtmp->chan, ones->chan);
119 76193d7c 2003-09-30 devnull if(dst==0 || src==0 || mask==0 || mtmp==0 || ones==0) {
120 76193d7c 2003-09-30 devnull Alloc:
121 76193d7c 2003-09-30 devnull fprint(2, "dtest: allocation failed: %r\n");
122 76193d7c 2003-09-30 devnull exits("alloc");
123 76193d7c 2003-09-30 devnull }
124 76193d7c 2003-09-30 devnull nbytes = (4*Xrange+4)*Yrange;
125 76193d7c 2003-09-30 devnull srcbits = malloc(nbytes);
126 76193d7c 2003-09-30 devnull dstbits = malloc(nbytes);
127 76193d7c 2003-09-30 devnull maskbits = malloc(nbytes);
128 76193d7c 2003-09-30 devnull savedstbits = malloc(nbytes);
129 76193d7c 2003-09-30 devnull if(dstbits==0 || srcbits==0 || maskbits==0 || savedstbits==0)
130 76193d7c 2003-09-30 devnull goto Alloc;
131 76193d7c 2003-09-30 devnull dbpp = dst->depth;
132 76193d7c 2003-09-30 devnull sbpp = src->depth;
133 76193d7c 2003-09-30 devnull mbpp = mask->depth;
134 76193d7c 2003-09-30 devnull dpm = 0xFF ^ (0xFF>>dbpp);
135 76193d7c 2003-09-30 devnull memset(ones->data->bdata, 0xFF, ones->width*sizeof(u32int)*Yrange);
136 76193d7c 2003-09-30 devnull
137 76193d7c 2003-09-30 devnull
138 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify single pixel operation\n");
139 76193d7c 2003-09-30 devnull verifyone();
140 76193d7c 2003-09-30 devnull
141 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify full line non-replicated\n");
142 76193d7c 2003-09-30 devnull verifyline();
143 76193d7c 2003-09-30 devnull
144 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify full rectangle non-replicated\n");
145 76193d7c 2003-09-30 devnull verifyrect();
146 76193d7c 2003-09-30 devnull
147 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify full rectangle source replicated\n");
148 76193d7c 2003-09-30 devnull verifyrectrepl(1, 0);
149 76193d7c 2003-09-30 devnull
150 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify full rectangle mask replicated\n");
151 76193d7c 2003-09-30 devnull verifyrectrepl(0, 1);
152 76193d7c 2003-09-30 devnull
153 76193d7c 2003-09-30 devnull fprint(2, "dtest: verify full rectangle source and mask replicated\n");
154 76193d7c 2003-09-30 devnull verifyrectrepl(1, 1);
155 76193d7c 2003-09-30 devnull
156 76193d7c 2003-09-30 devnull exits(0);
157 76193d7c 2003-09-30 devnull }
158 76193d7c 2003-09-30 devnull
159 76193d7c 2003-09-30 devnull /*
160 76193d7c 2003-09-30 devnull * Dump out an ASCII representation of an image. The label specifies
161 76193d7c 2003-09-30 devnull * a list of characters to put at various points in the picture.
162 76193d7c 2003-09-30 devnull */
163 76193d7c 2003-09-30 devnull static void
164 76193d7c 2003-09-30 devnull Bprintr5g6b5(Biobuf *bio, char*, u32int v)
165 76193d7c 2003-09-30 devnull {
166 76193d7c 2003-09-30 devnull int r,g,b;
167 76193d7c 2003-09-30 devnull r = (v>>11)&31;
168 76193d7c 2003-09-30 devnull g = (v>>5)&63;
169 76193d7c 2003-09-30 devnull b = v&31;
170 76193d7c 2003-09-30 devnull Bprint(bio, "%.2x%.2x%.2x", r,g,b);
171 76193d7c 2003-09-30 devnull }
172 76193d7c 2003-09-30 devnull
173 76193d7c 2003-09-30 devnull static void
174 76193d7c 2003-09-30 devnull Bprintr5g5b5a1(Biobuf *bio, char*, u32int v)
175 76193d7c 2003-09-30 devnull {
176 76193d7c 2003-09-30 devnull int r,g,b,a;
177 76193d7c 2003-09-30 devnull r = (v>>11)&31;
178 76193d7c 2003-09-30 devnull g = (v>>6)&31;
179 76193d7c 2003-09-30 devnull b = (v>>1)&31;
180 76193d7c 2003-09-30 devnull a = v&1;
181 76193d7c 2003-09-30 devnull Bprint(bio, "%.2x%.2x%.2x%.2x", r,g,b,a);
182 76193d7c 2003-09-30 devnull }
183 76193d7c 2003-09-30 devnull
184 76193d7c 2003-09-30 devnull void
185 76193d7c 2003-09-30 devnull dumpimage(char *name, Memimage *img, void *vdata, Point labelpt)
186 76193d7c 2003-09-30 devnull {
187 76193d7c 2003-09-30 devnull Biobuf b;
188 76193d7c 2003-09-30 devnull uchar *data;
189 76193d7c 2003-09-30 devnull uchar *p;
190 76193d7c 2003-09-30 devnull char *arg;
191 76193d7c 2003-09-30 devnull void (*fmt)(Biobuf*, char*, u32int);
192 76193d7c 2003-09-30 devnull int npr, x, y, nb, bpp;
193 76193d7c 2003-09-30 devnull u32int v, mask;
194 76193d7c 2003-09-30 devnull Rectangle r;
195 76193d7c 2003-09-30 devnull
196 76193d7c 2003-09-30 devnull fmt = nil;
197 76193d7c 2003-09-30 devnull arg = nil;
198 76193d7c 2003-09-30 devnull switch(img->depth){
199 76193d7c 2003-09-30 devnull case 1:
200 76193d7c 2003-09-30 devnull case 2:
201 76193d7c 2003-09-30 devnull case 4:
202 76193d7c 2003-09-30 devnull fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
203 76193d7c 2003-09-30 devnull arg = "%.1ux";
204 76193d7c 2003-09-30 devnull break;
205 76193d7c 2003-09-30 devnull case 8:
206 76193d7c 2003-09-30 devnull fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
207 76193d7c 2003-09-30 devnull arg = "%.2ux";
208 76193d7c 2003-09-30 devnull break;
209 76193d7c 2003-09-30 devnull case 16:
210 76193d7c 2003-09-30 devnull arg = nil;
211 76193d7c 2003-09-30 devnull if(img->chan == RGB16)
212 76193d7c 2003-09-30 devnull fmt = Bprintr5g6b5;
213 76193d7c 2003-09-30 devnull else{
214 76193d7c 2003-09-30 devnull fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
215 76193d7c 2003-09-30 devnull arg = "%.4ux";
216 76193d7c 2003-09-30 devnull }
217 76193d7c 2003-09-30 devnull break;
218 76193d7c 2003-09-30 devnull case 24:
219 76193d7c 2003-09-30 devnull fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
220 76193d7c 2003-09-30 devnull arg = "%.6lux";
221 76193d7c 2003-09-30 devnull break;
222 76193d7c 2003-09-30 devnull case 32:
223 76193d7c 2003-09-30 devnull fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
224 76193d7c 2003-09-30 devnull arg = "%.8lux";
225 76193d7c 2003-09-30 devnull break;
226 76193d7c 2003-09-30 devnull }
227 76193d7c 2003-09-30 devnull if(fmt == nil){
228 76193d7c 2003-09-30 devnull fprint(2, "bad format\n");
229 76193d7c 2003-09-30 devnull abort();
230 76193d7c 2003-09-30 devnull }
231 76193d7c 2003-09-30 devnull
232 76193d7c 2003-09-30 devnull r = img->r;
233 76193d7c 2003-09-30 devnull Binit(&b, 2, OWRITE);
234 76193d7c 2003-09-30 devnull data = vdata;
235 76193d7c 2003-09-30 devnull bpp = img->depth;
236 76193d7c 2003-09-30 devnull Bprint(&b, "%s\t%d\tr %R clipr %R repl %d data %p *%P\n", name, r.min.x, r, img->clipr, (img->flags&Frepl) ? 1 : 0, vdata, labelpt);
237 76193d7c 2003-09-30 devnull mask = (1ULL<<bpp)-1;
238 76193d7c 2003-09-30 devnull // for(y=r.min.y; y<r.max.y; y++){
239 76193d7c 2003-09-30 devnull for(y=0; y<Yrange; y++){
240 76193d7c 2003-09-30 devnull nb = 0;
241 76193d7c 2003-09-30 devnull v = 0;
242 76193d7c 2003-09-30 devnull p = data+(byteaddr(img, Pt(0,y))-(uchar*)img->data->bdata);
243 76193d7c 2003-09-30 devnull Bprint(&b, "%-4d\t", y);
244 76193d7c 2003-09-30 devnull // for(x=r.min.x; x<r.max.x; x++){
245 76193d7c 2003-09-30 devnull for(x=0; x<Xrange; x++){
246 76193d7c 2003-09-30 devnull if(x==0)
247 76193d7c 2003-09-30 devnull Bprint(&b, "\t");
248 76193d7c 2003-09-30 devnull
249 76193d7c 2003-09-30 devnull if(x != 0 && (x%8)==0)
250 76193d7c 2003-09-30 devnull Bprint(&b, " ");
251 76193d7c 2003-09-30 devnull
252 76193d7c 2003-09-30 devnull npr = 0;
253 76193d7c 2003-09-30 devnull if(x==labelpt.x && y==labelpt.y){
254 76193d7c 2003-09-30 devnull Bprint(&b, "*");
255 76193d7c 2003-09-30 devnull npr++;
256 76193d7c 2003-09-30 devnull }
257 76193d7c 2003-09-30 devnull if(npr == 0)
258 76193d7c 2003-09-30 devnull Bprint(&b, " ");
259 76193d7c 2003-09-30 devnull
260 76193d7c 2003-09-30 devnull while(nb < bpp){
261 76193d7c 2003-09-30 devnull v &= (1<<nb)-1;
262 76193d7c 2003-09-30 devnull v |= (u32int)(*p++) << nb;
263 76193d7c 2003-09-30 devnull nb += 8;
264 76193d7c 2003-09-30 devnull }
265 76193d7c 2003-09-30 devnull nb -= bpp;
266 76193d7c 2003-09-30 devnull // print("bpp %d v %.8lux mask %.8lux nb %d\n", bpp, v, mask, nb);
267 76193d7c 2003-09-30 devnull fmt(&b, arg, (v>>nb)&mask);
268 76193d7c 2003-09-30 devnull }
269 76193d7c 2003-09-30 devnull Bprint(&b, "\n");
270 76193d7c 2003-09-30 devnull }
271 76193d7c 2003-09-30 devnull Bterm(&b);
272 76193d7c 2003-09-30 devnull }
273 76193d7c 2003-09-30 devnull
274 76193d7c 2003-09-30 devnull /*
275 76193d7c 2003-09-30 devnull * Verify that the destination pixel has the specified value.
276 76193d7c 2003-09-30 devnull * The value is in the high bits of v, suitably masked, but must
277 76193d7c 2003-09-30 devnull * be extracted from the destination Memimage.
278 76193d7c 2003-09-30 devnull */
279 76193d7c 2003-09-30 devnull void
280 76193d7c 2003-09-30 devnull checkone(Point p, Point sp, Point mp)
281 76193d7c 2003-09-30 devnull {
282 76193d7c 2003-09-30 devnull int delta;
283 76193d7c 2003-09-30 devnull uchar *dp, *sdp;
284 76193d7c 2003-09-30 devnull
285 76193d7c 2003-09-30 devnull delta = (uchar*)byteaddr(dst, p)-(uchar*)dst->data->bdata;
286 76193d7c 2003-09-30 devnull dp = (uchar*)dst->data->bdata+delta;
287 76193d7c 2003-09-30 devnull sdp = (uchar*)savedstbits+delta;
288 76193d7c 2003-09-30 devnull
289 76193d7c 2003-09-30 devnull if(memcmp(dp, sdp, (dst->depth+7)/8) != 0) {
290 76193d7c 2003-09-30 devnull fprint(2, "dtest: one bad pixel drawing at dst %P from source %P mask %P\n", p, sp, mp);
291 76193d7c 2003-09-30 devnull fprint(2, " %.2ux %.2ux %.2ux %.2ux should be %.2ux %.2ux %.2ux %.2ux\n",
292 76193d7c 2003-09-30 devnull dp[0], dp[1], dp[2], dp[3], sdp[0], sdp[1], sdp[2], sdp[3]);
293 76193d7c 2003-09-30 devnull fprint(2, "addresses dst %p src %p mask %p\n", dp, byteaddr(src, sp), byteaddr(mask, mp));
294 76193d7c 2003-09-30 devnull dumpimage("src", src, src->data->bdata, sp);
295 76193d7c 2003-09-30 devnull dumpimage("mask", mask, mask->data->bdata, mp);
296 76193d7c 2003-09-30 devnull dumpimage("origdst", dst, dstbits, p);
297 76193d7c 2003-09-30 devnull dumpimage("dst", dst, dst->data->bdata, p);
298 76193d7c 2003-09-30 devnull dumpimage("gooddst", dst, savedstbits, p);
299 76193d7c 2003-09-30 devnull abort();
300 76193d7c 2003-09-30 devnull }
301 76193d7c 2003-09-30 devnull }
302 76193d7c 2003-09-30 devnull
303 76193d7c 2003-09-30 devnull /*
304 76193d7c 2003-09-30 devnull * Verify that the destination line has the same value as the saved line.
305 76193d7c 2003-09-30 devnull */
306 76193d7c 2003-09-30 devnull #define RECTPTS(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y
307 76193d7c 2003-09-30 devnull void
308 76193d7c 2003-09-30 devnull checkline(Rectangle r, Point sp, Point mp, int y, Memimage *stmp, Memimage *mtmp)
309 76193d7c 2003-09-30 devnull {
310 76193d7c 2003-09-30 devnull u32int *dp;
311 76193d7c 2003-09-30 devnull int nb;
312 76193d7c 2003-09-30 devnull u32int *saved;
313 76193d7c 2003-09-30 devnull
314 76193d7c 2003-09-30 devnull dp = wordaddr(dst, Pt(0, y));
315 76193d7c 2003-09-30 devnull saved = savedstbits + y*dst->width;
316 76193d7c 2003-09-30 devnull if(dst->depth < 8)
317 76193d7c 2003-09-30 devnull nb = Xrange/(8/dst->depth);
318 76193d7c 2003-09-30 devnull else
319 76193d7c 2003-09-30 devnull nb = Xrange*(dst->depth/8);
320 76193d7c 2003-09-30 devnull if(memcmp(dp, saved, nb) != 0){
321 76193d7c 2003-09-30 devnull fprint(2, "dtest: bad line at y=%d; saved %p dp %p\n", y, saved, dp);
322 76193d7c 2003-09-30 devnull fprint(2, "draw dst %R src %P mask %P\n", r, sp, mp);
323 76193d7c 2003-09-30 devnull dumpimage("src", src, src->data->bdata, sp);
324 76193d7c 2003-09-30 devnull if(stmp) dumpimage("stmp", stmp, stmp->data->bdata, sp);
325 76193d7c 2003-09-30 devnull dumpimage("mask", mask, mask->data->bdata, mp);
326 76193d7c 2003-09-30 devnull if(mtmp) dumpimage("mtmp", mtmp, mtmp->data->bdata, mp);
327 76193d7c 2003-09-30 devnull dumpimage("origdst", dst, dstbits, r.min);
328 76193d7c 2003-09-30 devnull dumpimage("dst", dst, dst->data->bdata, r.min);
329 76193d7c 2003-09-30 devnull dumpimage("gooddst", dst, savedstbits, r.min);
330 76193d7c 2003-09-30 devnull abort();
331 76193d7c 2003-09-30 devnull }
332 76193d7c 2003-09-30 devnull }
333 76193d7c 2003-09-30 devnull
334 76193d7c 2003-09-30 devnull /*
335 76193d7c 2003-09-30 devnull * Fill the bits of an image with random data.
336 76193d7c 2003-09-30 devnull * The Memimage parameter is used only to make sure
337 76193d7c 2003-09-30 devnull * the data is well formatted: only ucbits is written.
338 76193d7c 2003-09-30 devnull */
339 76193d7c 2003-09-30 devnull void
340 76193d7c 2003-09-30 devnull fill(Memimage *img, uchar *ucbits)
341 76193d7c 2003-09-30 devnull {
342 76193d7c 2003-09-30 devnull int i, x, y;
343 76193d7c 2003-09-30 devnull ushort *up;
344 76193d7c 2003-09-30 devnull uchar alpha, r, g, b;
345 76193d7c 2003-09-30 devnull void *data;
346 76193d7c 2003-09-30 devnull
347 76193d7c 2003-09-30 devnull if((img->flags&Falpha) == 0){
348 76193d7c 2003-09-30 devnull up = (ushort*)ucbits;
349 76193d7c 2003-09-30 devnull for(i=0; i<nbytes/2; i++)
350 76193d7c 2003-09-30 devnull *up++ = lrand() >> 7;
351 76193d7c 2003-09-30 devnull if(i+i != nbytes)
352 76193d7c 2003-09-30 devnull *(uchar*)up = lrand() >> 7;
353 76193d7c 2003-09-30 devnull }else{
354 76193d7c 2003-09-30 devnull data = img->data->bdata;
355 76193d7c 2003-09-30 devnull img->data->bdata = ucbits;
356 76193d7c 2003-09-30 devnull
357 76193d7c 2003-09-30 devnull for(x=img->r.min.x; x<img->r.max.x; x++)
358 76193d7c 2003-09-30 devnull for(y=img->r.min.y; y<img->r.max.y; y++){
359 76193d7c 2003-09-30 devnull alpha = rand() >> 4;
360 76193d7c 2003-09-30 devnull r = rand()%(alpha+1);
361 76193d7c 2003-09-30 devnull g = rand()%(alpha+1);
362 76193d7c 2003-09-30 devnull b = rand()%(alpha+1);
363 76193d7c 2003-09-30 devnull putpixel(img, Pt(x,y), rgbatopix(r,g,b,alpha));
364 76193d7c 2003-09-30 devnull }
365 76193d7c 2003-09-30 devnull img->data->bdata = data;
366 76193d7c 2003-09-30 devnull }
367 76193d7c 2003-09-30 devnull
368 76193d7c 2003-09-30 devnull }
369 76193d7c 2003-09-30 devnull
370 76193d7c 2003-09-30 devnull /*
371 76193d7c 2003-09-30 devnull * Mask is preset; do the rest
372 76193d7c 2003-09-30 devnull */
373 76193d7c 2003-09-30 devnull void
374 76193d7c 2003-09-30 devnull verifyonemask(void)
375 76193d7c 2003-09-30 devnull {
376 76193d7c 2003-09-30 devnull Point dp, sp, mp;
377 76193d7c 2003-09-30 devnull
378 76193d7c 2003-09-30 devnull fill(dst, dstbits);
379 76193d7c 2003-09-30 devnull fill(src, srcbits);
380 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
381 76193d7c 2003-09-30 devnull memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
382 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
383 76193d7c 2003-09-30 devnull
384 76193d7c 2003-09-30 devnull dp.x = nrand(Xrange);
385 76193d7c 2003-09-30 devnull dp.y = nrand(Yrange);
386 76193d7c 2003-09-30 devnull
387 76193d7c 2003-09-30 devnull sp.x = nrand(Xrange);
388 76193d7c 2003-09-30 devnull sp.y = nrand(Yrange);
389 76193d7c 2003-09-30 devnull
390 76193d7c 2003-09-30 devnull mp.x = nrand(Xrange);
391 76193d7c 2003-09-30 devnull mp.y = nrand(Yrange);
392 76193d7c 2003-09-30 devnull
393 76193d7c 2003-09-30 devnull drawonepixel(dst, dp, src, sp, mask, mp);
394 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
395 76193d7c 2003-09-30 devnull memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
396 76193d7c 2003-09-30 devnull
397 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
398 76193d7c 2003-09-30 devnull memimagedraw(dst, Rect(dp.x, dp.y, dp.x+1, dp.y+1), src, sp, mask, mp, SoverD);
399 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
400 76193d7c 2003-09-30 devnull
401 76193d7c 2003-09-30 devnull checkone(dp, sp, mp);
402 76193d7c 2003-09-30 devnull }
403 76193d7c 2003-09-30 devnull
404 76193d7c 2003-09-30 devnull void
405 76193d7c 2003-09-30 devnull verifyone(void)
406 76193d7c 2003-09-30 devnull {
407 76193d7c 2003-09-30 devnull int i;
408 76193d7c 2003-09-30 devnull
409 76193d7c 2003-09-30 devnull /* mask all zeros */
410 76193d7c 2003-09-30 devnull memset(maskbits, 0, nbytes);
411 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
412 76193d7c 2003-09-30 devnull verifyonemask();
413 76193d7c 2003-09-30 devnull
414 76193d7c 2003-09-30 devnull /* mask all ones */
415 76193d7c 2003-09-30 devnull memset(maskbits, 0xFF, nbytes);
416 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
417 76193d7c 2003-09-30 devnull verifyonemask();
418 76193d7c 2003-09-30 devnull
419 76193d7c 2003-09-30 devnull /* random mask */
420 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++){
421 76193d7c 2003-09-30 devnull fill(mask, maskbits);
422 76193d7c 2003-09-30 devnull verifyonemask();
423 76193d7c 2003-09-30 devnull }
424 76193d7c 2003-09-30 devnull }
425 76193d7c 2003-09-30 devnull
426 76193d7c 2003-09-30 devnull /*
427 76193d7c 2003-09-30 devnull * Mask is preset; do the rest
428 76193d7c 2003-09-30 devnull */
429 76193d7c 2003-09-30 devnull void
430 76193d7c 2003-09-30 devnull verifylinemask(void)
431 76193d7c 2003-09-30 devnull {
432 76193d7c 2003-09-30 devnull Point sp, mp, tp, up;
433 76193d7c 2003-09-30 devnull Rectangle dr;
434 76193d7c 2003-09-30 devnull int x;
435 76193d7c 2003-09-30 devnull
436 76193d7c 2003-09-30 devnull fill(dst, dstbits);
437 76193d7c 2003-09-30 devnull fill(src, srcbits);
438 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
439 76193d7c 2003-09-30 devnull memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
440 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
441 76193d7c 2003-09-30 devnull
442 76193d7c 2003-09-30 devnull dr.min.x = nrand(Xrange-1);
443 76193d7c 2003-09-30 devnull dr.min.y = nrand(Yrange-1);
444 76193d7c 2003-09-30 devnull dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x);
445 76193d7c 2003-09-30 devnull dr.max.y = dr.min.y + 1;
446 76193d7c 2003-09-30 devnull
447 76193d7c 2003-09-30 devnull sp.x = nrand(Xrange);
448 76193d7c 2003-09-30 devnull sp.y = nrand(Yrange);
449 76193d7c 2003-09-30 devnull
450 76193d7c 2003-09-30 devnull mp.x = nrand(Xrange);
451 76193d7c 2003-09-30 devnull mp.y = nrand(Yrange);
452 76193d7c 2003-09-30 devnull
453 76193d7c 2003-09-30 devnull tp = sp;
454 76193d7c 2003-09-30 devnull up = mp;
455 76193d7c 2003-09-30 devnull for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
456 76193d7c 2003-09-30 devnull memimagedraw(dst, Rect(x, dr.min.y, x+1, dr.min.y+1), src, tp, mask, up, SoverD);
457 76193d7c 2003-09-30 devnull memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
458 76193d7c 2003-09-30 devnull
459 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
460 76193d7c 2003-09-30 devnull
461 76193d7c 2003-09-30 devnull memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
462 76193d7c 2003-09-30 devnull checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), dr.min.y, nil, nil);
463 76193d7c 2003-09-30 devnull }
464 76193d7c 2003-09-30 devnull
465 76193d7c 2003-09-30 devnull void
466 76193d7c 2003-09-30 devnull verifyline(void)
467 76193d7c 2003-09-30 devnull {
468 76193d7c 2003-09-30 devnull int i;
469 76193d7c 2003-09-30 devnull
470 76193d7c 2003-09-30 devnull /* mask all ones */
471 76193d7c 2003-09-30 devnull memset(maskbits, 0xFF, nbytes);
472 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
473 76193d7c 2003-09-30 devnull verifylinemask();
474 76193d7c 2003-09-30 devnull
475 76193d7c 2003-09-30 devnull /* mask all zeros */
476 76193d7c 2003-09-30 devnull memset(maskbits, 0, nbytes);
477 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
478 76193d7c 2003-09-30 devnull verifylinemask();
479 76193d7c 2003-09-30 devnull
480 76193d7c 2003-09-30 devnull /* random mask */
481 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++){
482 76193d7c 2003-09-30 devnull fill(mask, maskbits);
483 76193d7c 2003-09-30 devnull verifylinemask();
484 76193d7c 2003-09-30 devnull }
485 76193d7c 2003-09-30 devnull }
486 76193d7c 2003-09-30 devnull
487 76193d7c 2003-09-30 devnull /*
488 76193d7c 2003-09-30 devnull * Mask is preset; do the rest
489 76193d7c 2003-09-30 devnull */
490 76193d7c 2003-09-30 devnull void
491 76193d7c 2003-09-30 devnull verifyrectmask(void)
492 76193d7c 2003-09-30 devnull {
493 76193d7c 2003-09-30 devnull Point sp, mp, tp, up;
494 76193d7c 2003-09-30 devnull Rectangle dr;
495 76193d7c 2003-09-30 devnull int x, y;
496 76193d7c 2003-09-30 devnull
497 76193d7c 2003-09-30 devnull fill(dst, dstbits);
498 76193d7c 2003-09-30 devnull fill(src, srcbits);
499 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
500 76193d7c 2003-09-30 devnull memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
501 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
502 76193d7c 2003-09-30 devnull
503 76193d7c 2003-09-30 devnull dr.min.x = nrand(Xrange-1);
504 76193d7c 2003-09-30 devnull dr.min.y = nrand(Yrange-1);
505 76193d7c 2003-09-30 devnull dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x);
506 76193d7c 2003-09-30 devnull dr.max.y = dr.min.y + 1 + nrand(Yrange-1-dr.min.y);
507 76193d7c 2003-09-30 devnull
508 76193d7c 2003-09-30 devnull sp.x = nrand(Xrange);
509 76193d7c 2003-09-30 devnull sp.y = nrand(Yrange);
510 76193d7c 2003-09-30 devnull
511 76193d7c 2003-09-30 devnull mp.x = nrand(Xrange);
512 76193d7c 2003-09-30 devnull mp.y = nrand(Yrange);
513 76193d7c 2003-09-30 devnull
514 76193d7c 2003-09-30 devnull tp = sp;
515 76193d7c 2003-09-30 devnull up = mp;
516 76193d7c 2003-09-30 devnull for(y=dr.min.y; y<dr.max.y && tp.y<Yrange && up.y<Yrange; y++,tp.y++,up.y++){
517 76193d7c 2003-09-30 devnull for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
518 76193d7c 2003-09-30 devnull memimagedraw(dst, Rect(x, y, x+1, y+1), src, tp, mask, up, SoverD);
519 76193d7c 2003-09-30 devnull tp.x = sp.x;
520 76193d7c 2003-09-30 devnull up.x = mp.x;
521 76193d7c 2003-09-30 devnull }
522 76193d7c 2003-09-30 devnull memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
523 76193d7c 2003-09-30 devnull
524 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
525 76193d7c 2003-09-30 devnull
526 76193d7c 2003-09-30 devnull memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
527 76193d7c 2003-09-30 devnull for(y=0; y<Yrange; y++)
528 76193d7c 2003-09-30 devnull checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, nil, nil);
529 76193d7c 2003-09-30 devnull }
530 76193d7c 2003-09-30 devnull
531 76193d7c 2003-09-30 devnull void
532 76193d7c 2003-09-30 devnull verifyrect(void)
533 76193d7c 2003-09-30 devnull {
534 76193d7c 2003-09-30 devnull int i;
535 76193d7c 2003-09-30 devnull
536 76193d7c 2003-09-30 devnull /* mask all zeros */
537 76193d7c 2003-09-30 devnull memset(maskbits, 0, nbytes);
538 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
539 76193d7c 2003-09-30 devnull verifyrectmask();
540 76193d7c 2003-09-30 devnull
541 76193d7c 2003-09-30 devnull /* mask all ones */
542 76193d7c 2003-09-30 devnull memset(maskbits, 0xFF, nbytes);
543 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
544 76193d7c 2003-09-30 devnull verifyrectmask();
545 76193d7c 2003-09-30 devnull
546 76193d7c 2003-09-30 devnull /* random mask */
547 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++){
548 76193d7c 2003-09-30 devnull fill(mask, maskbits);
549 76193d7c 2003-09-30 devnull verifyrectmask();
550 76193d7c 2003-09-30 devnull }
551 76193d7c 2003-09-30 devnull }
552 76193d7c 2003-09-30 devnull
553 76193d7c 2003-09-30 devnull Rectangle
554 76193d7c 2003-09-30 devnull randrect(void)
555 76193d7c 2003-09-30 devnull {
556 76193d7c 2003-09-30 devnull Rectangle r;
557 76193d7c 2003-09-30 devnull
558 76193d7c 2003-09-30 devnull r.min.x = nrand(Xrange-1);
559 76193d7c 2003-09-30 devnull r.min.y = nrand(Yrange-1);
560 76193d7c 2003-09-30 devnull r.max.x = r.min.x + 1 + nrand(Xrange-1-r.min.x);
561 76193d7c 2003-09-30 devnull r.max.y = r.min.y + 1 + nrand(Yrange-1-r.min.y);
562 76193d7c 2003-09-30 devnull return r;
563 76193d7c 2003-09-30 devnull }
564 76193d7c 2003-09-30 devnull
565 76193d7c 2003-09-30 devnull /*
566 76193d7c 2003-09-30 devnull * Return coordinate corresponding to x withing range [minx, maxx)
567 76193d7c 2003-09-30 devnull */
568 76193d7c 2003-09-30 devnull int
569 76193d7c 2003-09-30 devnull tilexy(int minx, int maxx, int x)
570 76193d7c 2003-09-30 devnull {
571 76193d7c 2003-09-30 devnull int sx;
572 76193d7c 2003-09-30 devnull
573 76193d7c 2003-09-30 devnull sx = (x-minx) % (maxx-minx);
574 76193d7c 2003-09-30 devnull if(sx < 0)
575 76193d7c 2003-09-30 devnull sx += maxx-minx;
576 76193d7c 2003-09-30 devnull return sx+minx;
577 76193d7c 2003-09-30 devnull }
578 76193d7c 2003-09-30 devnull
579 76193d7c 2003-09-30 devnull void
580 76193d7c 2003-09-30 devnull replicate(Memimage *i, Memimage *tmp)
581 76193d7c 2003-09-30 devnull {
582 76193d7c 2003-09-30 devnull Rectangle r, r1;
583 76193d7c 2003-09-30 devnull int x, y, nb;
584 76193d7c 2003-09-30 devnull
585 76193d7c 2003-09-30 devnull /* choose the replication window (i->r) */
586 76193d7c 2003-09-30 devnull r.min.x = nrand(Xrange-1);
587 76193d7c 2003-09-30 devnull r.min.y = nrand(Yrange-1);
588 76193d7c 2003-09-30 devnull /* make it trivial more often than pure chance allows */
589 76193d7c 2003-09-30 devnull switch(lrand()&0){
590 76193d7c 2003-09-30 devnull case 1:
591 76193d7c 2003-09-30 devnull r.max.x = r.min.x + 2;
592 76193d7c 2003-09-30 devnull r.max.y = r.min.y + 2;
593 76193d7c 2003-09-30 devnull if(r.max.x < Xrange && r.max.y < Yrange)
594 76193d7c 2003-09-30 devnull break;
595 76193d7c 2003-09-30 devnull /* fall through */
596 76193d7c 2003-09-30 devnull case 0:
597 76193d7c 2003-09-30 devnull r.max.x = r.min.x + 1;
598 76193d7c 2003-09-30 devnull r.max.y = r.min.y + 1;
599 76193d7c 2003-09-30 devnull break;
600 76193d7c 2003-09-30 devnull default:
601 76193d7c 2003-09-30 devnull if(r.min.x+3 >= Xrange)
602 76193d7c 2003-09-30 devnull r.max.x = Xrange;
603 76193d7c 2003-09-30 devnull else
604 76193d7c 2003-09-30 devnull r.max.x = r.min.x+3 + nrand(Xrange-(r.min.x+3));
605 76193d7c 2003-09-30 devnull
606 76193d7c 2003-09-30 devnull if(r.min.y+3 >= Yrange)
607 76193d7c 2003-09-30 devnull r.max.y = Yrange;
608 76193d7c 2003-09-30 devnull else
609 76193d7c 2003-09-30 devnull r.max.y = r.min.y+3 + nrand(Yrange-(r.min.y+3));
610 76193d7c 2003-09-30 devnull }
611 76193d7c 2003-09-30 devnull assert(r.min.x >= 0);
612 76193d7c 2003-09-30 devnull assert(r.max.x <= Xrange);
613 76193d7c 2003-09-30 devnull assert(r.min.y >= 0);
614 76193d7c 2003-09-30 devnull assert(r.max.y <= Yrange);
615 76193d7c 2003-09-30 devnull /* copy from i to tmp so we have just the replicated bits */
616 76193d7c 2003-09-30 devnull nb = tmp->width*sizeof(u32int)*Yrange;
617 76193d7c 2003-09-30 devnull memset(tmp->data->bdata, 0, nb);
618 76193d7c 2003-09-30 devnull memimagedraw(tmp, r, i, r.min, ones, r.min, SoverD);
619 76193d7c 2003-09-30 devnull memmove(i->data->bdata, tmp->data->bdata, nb);
620 76193d7c 2003-09-30 devnull /* i is now a non-replicated instance of the replication */
621 76193d7c 2003-09-30 devnull /* replicate it by hand through tmp */
622 76193d7c 2003-09-30 devnull memset(tmp->data->bdata, 0, nb);
623 76193d7c 2003-09-30 devnull x = -(tilexy(r.min.x, r.max.x, 0)-r.min.x);
624 76193d7c 2003-09-30 devnull for(; x<Xrange; x+=Dx(r)){
625 76193d7c 2003-09-30 devnull y = -(tilexy(r.min.y, r.max.y, 0)-r.min.y);
626 76193d7c 2003-09-30 devnull for(; y<Yrange; y+=Dy(r)){
627 76193d7c 2003-09-30 devnull /* set r1 to instance of tile by translation */
628 76193d7c 2003-09-30 devnull r1.min.x = x;
629 76193d7c 2003-09-30 devnull r1.min.y = y;
630 76193d7c 2003-09-30 devnull r1.max.x = r1.min.x+Dx(r);
631 76193d7c 2003-09-30 devnull r1.max.y = r1.min.y+Dy(r);
632 76193d7c 2003-09-30 devnull memimagedraw(tmp, r1, i, r.min, ones, r.min, SoverD);
633 76193d7c 2003-09-30 devnull }
634 76193d7c 2003-09-30 devnull }
635 76193d7c 2003-09-30 devnull i->flags |= Frepl;
636 76193d7c 2003-09-30 devnull i->r = r;
637 76193d7c 2003-09-30 devnull i->clipr = randrect();
638 76193d7c 2003-09-30 devnull // fprint(2, "replicate [[%d %d] [%d %d]] [[%d %d][%d %d]]\n", r.min.x, r.min.y, r.max.x, r.max.y,
639 76193d7c 2003-09-30 devnull // i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
640 76193d7c 2003-09-30 devnull tmp->clipr = i->clipr;
641 76193d7c 2003-09-30 devnull }
642 76193d7c 2003-09-30 devnull
643 76193d7c 2003-09-30 devnull /*
644 76193d7c 2003-09-30 devnull * Mask is preset; do the rest
645 76193d7c 2003-09-30 devnull */
646 76193d7c 2003-09-30 devnull void
647 76193d7c 2003-09-30 devnull verifyrectmaskrepl(int srcrepl, int maskrepl)
648 76193d7c 2003-09-30 devnull {
649 76193d7c 2003-09-30 devnull Point sp, mp, tp, up;
650 76193d7c 2003-09-30 devnull Rectangle dr;
651 76193d7c 2003-09-30 devnull int x, y;
652 76193d7c 2003-09-30 devnull Memimage *s, *m;
653 76193d7c 2003-09-30 devnull
654 76193d7c 2003-09-30 devnull // print("verfrect %d %d\n", srcrepl, maskrepl);
655 76193d7c 2003-09-30 devnull src->flags &= ~Frepl;
656 76193d7c 2003-09-30 devnull src->r = Rect(0, 0, Xrange, Yrange);
657 76193d7c 2003-09-30 devnull src->clipr = src->r;
658 76193d7c 2003-09-30 devnull stmp->flags &= ~Frepl;
659 76193d7c 2003-09-30 devnull stmp->r = Rect(0, 0, Xrange, Yrange);
660 76193d7c 2003-09-30 devnull stmp->clipr = src->r;
661 76193d7c 2003-09-30 devnull mask->flags &= ~Frepl;
662 76193d7c 2003-09-30 devnull mask->r = Rect(0, 0, Xrange, Yrange);
663 76193d7c 2003-09-30 devnull mask->clipr = mask->r;
664 76193d7c 2003-09-30 devnull mtmp->flags &= ~Frepl;
665 76193d7c 2003-09-30 devnull mtmp->r = Rect(0, 0, Xrange, Yrange);
666 76193d7c 2003-09-30 devnull mtmp->clipr = mask->r;
667 76193d7c 2003-09-30 devnull
668 76193d7c 2003-09-30 devnull fill(dst, dstbits);
669 76193d7c 2003-09-30 devnull fill(src, srcbits);
670 76193d7c 2003-09-30 devnull
671 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
672 76193d7c 2003-09-30 devnull memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
673 76193d7c 2003-09-30 devnull memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
674 76193d7c 2003-09-30 devnull
675 76193d7c 2003-09-30 devnull if(srcrepl){
676 76193d7c 2003-09-30 devnull replicate(src, stmp);
677 76193d7c 2003-09-30 devnull s = stmp;
678 76193d7c 2003-09-30 devnull }else
679 76193d7c 2003-09-30 devnull s = src;
680 76193d7c 2003-09-30 devnull if(maskrepl){
681 76193d7c 2003-09-30 devnull replicate(mask, mtmp);
682 76193d7c 2003-09-30 devnull m = mtmp;
683 76193d7c 2003-09-30 devnull }else
684 76193d7c 2003-09-30 devnull m = mask;
685 76193d7c 2003-09-30 devnull
686 76193d7c 2003-09-30 devnull dr = randrect();
687 76193d7c 2003-09-30 devnull
688 76193d7c 2003-09-30 devnull sp.x = nrand(Xrange);
689 76193d7c 2003-09-30 devnull sp.y = nrand(Yrange);
690 76193d7c 2003-09-30 devnull
691 76193d7c 2003-09-30 devnull mp.x = nrand(Xrange);
692 76193d7c 2003-09-30 devnull mp.y = nrand(Yrange);
693 76193d7c 2003-09-30 devnull
694 76193d7c 2003-09-30 devnull DBG print("smalldraws\n");
695 76193d7c 2003-09-30 devnull for(tp.y=sp.y,up.y=mp.y,y=dr.min.y; y<dr.max.y && tp.y<Yrange && up.y<Yrange; y++,tp.y++,up.y++)
696 76193d7c 2003-09-30 devnull for(tp.x=sp.x,up.x=mp.x,x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
697 76193d7c 2003-09-30 devnull memimagedraw(dst, Rect(x, y, x+1, y+1), s, tp, m, up, SoverD);
698 76193d7c 2003-09-30 devnull memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
699 76193d7c 2003-09-30 devnull
700 76193d7c 2003-09-30 devnull memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
701 76193d7c 2003-09-30 devnull
702 76193d7c 2003-09-30 devnull DBG print("bigdraw\n");
703 76193d7c 2003-09-30 devnull memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
704 76193d7c 2003-09-30 devnull for(y=0; y<Yrange; y++)
705 76193d7c 2003-09-30 devnull checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, srcrepl?stmp:nil, maskrepl?mtmp:nil);
706 76193d7c 2003-09-30 devnull }
707 76193d7c 2003-09-30 devnull
708 76193d7c 2003-09-30 devnull void
709 76193d7c 2003-09-30 devnull verifyrectrepl(int srcrepl, int maskrepl)
710 76193d7c 2003-09-30 devnull {
711 76193d7c 2003-09-30 devnull int i;
712 76193d7c 2003-09-30 devnull
713 76193d7c 2003-09-30 devnull /* mask all ones */
714 76193d7c 2003-09-30 devnull memset(maskbits, 0xFF, nbytes);
715 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
716 76193d7c 2003-09-30 devnull verifyrectmaskrepl(srcrepl, maskrepl);
717 76193d7c 2003-09-30 devnull
718 76193d7c 2003-09-30 devnull /* mask all zeros */
719 76193d7c 2003-09-30 devnull memset(maskbits, 0, nbytes);
720 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++)
721 76193d7c 2003-09-30 devnull verifyrectmaskrepl(srcrepl, maskrepl);
722 76193d7c 2003-09-30 devnull
723 76193d7c 2003-09-30 devnull /* random mask */
724 76193d7c 2003-09-30 devnull for(i=0; i<niters; i++){
725 76193d7c 2003-09-30 devnull fill(mask, maskbits);
726 76193d7c 2003-09-30 devnull verifyrectmaskrepl(srcrepl, maskrepl);
727 76193d7c 2003-09-30 devnull }
728 76193d7c 2003-09-30 devnull }
729 76193d7c 2003-09-30 devnull
730 76193d7c 2003-09-30 devnull /*
731 76193d7c 2003-09-30 devnull * Trivial draw implementation.
732 76193d7c 2003-09-30 devnull * Color values are passed around as u32ints containing ααRRGGBB
733 76193d7c 2003-09-30 devnull */
734 76193d7c 2003-09-30 devnull
735 76193d7c 2003-09-30 devnull /*
736 76193d7c 2003-09-30 devnull * Convert v, which is nhave bits wide, into its nwant bits wide equivalent.
737 76193d7c 2003-09-30 devnull * Replicates to widen the value, truncates to narrow it.
738 76193d7c 2003-09-30 devnull */
739 76193d7c 2003-09-30 devnull u32int
740 76193d7c 2003-09-30 devnull replbits(u32int v, int nhave, int nwant)
741 76193d7c 2003-09-30 devnull {
742 76193d7c 2003-09-30 devnull v &= (1<<nhave)-1;
743 76193d7c 2003-09-30 devnull for(; nhave<nwant; nhave*=2)
744 76193d7c 2003-09-30 devnull v |= v<<nhave;
745 76193d7c 2003-09-30 devnull v >>= (nhave-nwant);
746 76193d7c 2003-09-30 devnull return v & ((1<<nwant)-1);
747 76193d7c 2003-09-30 devnull }
748 76193d7c 2003-09-30 devnull
749 76193d7c 2003-09-30 devnull /*
750 76193d7c 2003-09-30 devnull * Decode a pixel into the uchar* values.
751 76193d7c 2003-09-30 devnull */
752 76193d7c 2003-09-30 devnull void
753 76193d7c 2003-09-30 devnull pixtorgba(u32int v, uchar *r, uchar *g, uchar *b, uchar *a)
754 76193d7c 2003-09-30 devnull {
755 76193d7c 2003-09-30 devnull *a = v>>24;
756 76193d7c 2003-09-30 devnull *r = v>>16;
757 76193d7c 2003-09-30 devnull *g = v>>8;
758 76193d7c 2003-09-30 devnull *b = v;
759 76193d7c 2003-09-30 devnull }
760 76193d7c 2003-09-30 devnull
761 76193d7c 2003-09-30 devnull /*
762 76193d7c 2003-09-30 devnull * Convert uchar channels into u32int pixel.
763 76193d7c 2003-09-30 devnull */
764 76193d7c 2003-09-30 devnull u32int
765 76193d7c 2003-09-30 devnull rgbatopix(uchar r, uchar g, uchar b, uchar a)
766 76193d7c 2003-09-30 devnull {
767 76193d7c 2003-09-30 devnull return (a<<24)|(r<<16)|(g<<8)|b;
768 76193d7c 2003-09-30 devnull }
769 76193d7c 2003-09-30 devnull
770 76193d7c 2003-09-30 devnull /*
771 76193d7c 2003-09-30 devnull * Retrieve the pixel value at pt in the image.
772 76193d7c 2003-09-30 devnull */
773 76193d7c 2003-09-30 devnull u32int
774 76193d7c 2003-09-30 devnull getpixel(Memimage *img, Point pt)
775 76193d7c 2003-09-30 devnull {
776 76193d7c 2003-09-30 devnull uchar r, g, b, a, *p;
777 76193d7c 2003-09-30 devnull int nbits, npack, bpp;
778 76193d7c 2003-09-30 devnull u32int v, c, rbits, bits;
779 76193d7c 2003-09-30 devnull
780 76193d7c 2003-09-30 devnull r = g = b = 0;
781 76193d7c 2003-09-30 devnull a = ~0; /* default alpha is full */
782 76193d7c 2003-09-30 devnull
783 76193d7c 2003-09-30 devnull p = byteaddr(img, pt);
784 76193d7c 2003-09-30 devnull v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
785 76193d7c 2003-09-30 devnull bpp = img->depth;
786 76193d7c 2003-09-30 devnull if(bpp<8){
787 76193d7c 2003-09-30 devnull /*
788 76193d7c 2003-09-30 devnull * Sub-byte greyscale pixels.
789 76193d7c 2003-09-30 devnull *
790 76193d7c 2003-09-30 devnull * We want to throw away the top pt.x%npack pixels and then use the next bpp bits
791 76193d7c 2003-09-30 devnull * in the bottom byte of v. This madness is due to having big endian bits
792 76193d7c 2003-09-30 devnull * but little endian bytes.
793 76193d7c 2003-09-30 devnull */
794 76193d7c 2003-09-30 devnull npack = 8/bpp;
795 76193d7c 2003-09-30 devnull v >>= 8 - bpp*(pt.x%npack+1);
796 76193d7c 2003-09-30 devnull v &= (1<<bpp)-1;
797 76193d7c 2003-09-30 devnull r = g = b = replbits(v, bpp, 8);
798 76193d7c 2003-09-30 devnull }else{
799 76193d7c 2003-09-30 devnull /*
800 76193d7c 2003-09-30 devnull * General case. We need to parse the channel descriptor and do what it says.
801 76193d7c 2003-09-30 devnull * In all channels but the color map, we replicate to 8 bits because that's the
802 76193d7c 2003-09-30 devnull * precision that all calculations are done at.
803 76193d7c 2003-09-30 devnull *
804 76193d7c 2003-09-30 devnull * In the case of the color map, we leave the bits alone, in case a color map
805 76193d7c 2003-09-30 devnull * with less than 8 bits of index is used. This is currently disallowed, so it's
806 76193d7c 2003-09-30 devnull * sort of silly.
807 76193d7c 2003-09-30 devnull */
808 76193d7c 2003-09-30 devnull
809 76193d7c 2003-09-30 devnull for(c=img->chan; c; c>>=8){
810 76193d7c 2003-09-30 devnull nbits = NBITS(c);
811 76193d7c 2003-09-30 devnull bits = v & ((1<<nbits)-1);
812 76193d7c 2003-09-30 devnull rbits = replbits(bits, nbits, 8);
813 76193d7c 2003-09-30 devnull v >>= nbits;
814 76193d7c 2003-09-30 devnull switch(TYPE(c)){
815 76193d7c 2003-09-30 devnull case CRed:
816 76193d7c 2003-09-30 devnull r = rbits;
817 76193d7c 2003-09-30 devnull break;
818 76193d7c 2003-09-30 devnull case CGreen:
819 76193d7c 2003-09-30 devnull g = rbits;
820 76193d7c 2003-09-30 devnull break;
821 76193d7c 2003-09-30 devnull case CBlue:
822 76193d7c 2003-09-30 devnull b = rbits;
823 76193d7c 2003-09-30 devnull break;
824 76193d7c 2003-09-30 devnull case CGrey:
825 76193d7c 2003-09-30 devnull r = g = b = rbits;
826 76193d7c 2003-09-30 devnull break;
827 76193d7c 2003-09-30 devnull case CAlpha:
828 76193d7c 2003-09-30 devnull a = rbits;
829 76193d7c 2003-09-30 devnull break;
830 76193d7c 2003-09-30 devnull case CMap:
831 76193d7c 2003-09-30 devnull p = img->cmap->cmap2rgb + 3*bits;
832 76193d7c 2003-09-30 devnull r = p[0];
833 76193d7c 2003-09-30 devnull g = p[1];
834 76193d7c 2003-09-30 devnull b = p[2];
835 76193d7c 2003-09-30 devnull break;
836 76193d7c 2003-09-30 devnull case CIgnore:
837 76193d7c 2003-09-30 devnull break;
838 76193d7c 2003-09-30 devnull default:
839 76193d7c 2003-09-30 devnull fprint(2, "unknown channel type %lud\n", TYPE(c));
840 76193d7c 2003-09-30 devnull abort();
841 76193d7c 2003-09-30 devnull }
842 76193d7c 2003-09-30 devnull }
843 76193d7c 2003-09-30 devnull }
844 76193d7c 2003-09-30 devnull return rgbatopix(r, g, b, a);
845 76193d7c 2003-09-30 devnull }
846 76193d7c 2003-09-30 devnull
847 76193d7c 2003-09-30 devnull /*
848 76193d7c 2003-09-30 devnull * Return the greyscale equivalent of a pixel.
849 76193d7c 2003-09-30 devnull */
850 76193d7c 2003-09-30 devnull uchar
851 76193d7c 2003-09-30 devnull getgrey(Memimage *img, Point pt)
852 76193d7c 2003-09-30 devnull {
853 76193d7c 2003-09-30 devnull uchar r, g, b, a;
854 76193d7c 2003-09-30 devnull pixtorgba(getpixel(img, pt), &r, &g, &b, &a);
855 76193d7c 2003-09-30 devnull return RGB2K(r, g, b);
856 76193d7c 2003-09-30 devnull }
857 76193d7c 2003-09-30 devnull
858 76193d7c 2003-09-30 devnull /*
859 76193d7c 2003-09-30 devnull * Return the value at pt in image, if image is interpreted
860 76193d7c 2003-09-30 devnull * as a mask. This means the alpha channel if present, else
861 76193d7c 2003-09-30 devnull * the greyscale or its computed equivalent.
862 76193d7c 2003-09-30 devnull */
863 76193d7c 2003-09-30 devnull uchar
864 76193d7c 2003-09-30 devnull getmask(Memimage *img, Point pt)
865 76193d7c 2003-09-30 devnull {
866 76193d7c 2003-09-30 devnull if(img->flags&Falpha)
867 76193d7c 2003-09-30 devnull return getpixel(img, pt)>>24;
868 76193d7c 2003-09-30 devnull else
869 76193d7c 2003-09-30 devnull return getgrey(img, pt);
870 76193d7c 2003-09-30 devnull }
871 76193d7c 2003-09-30 devnull #undef DBG
872 76193d7c 2003-09-30 devnull
873 76193d7c 2003-09-30 devnull #define DBG if(0)
874 76193d7c 2003-09-30 devnull /*
875 76193d7c 2003-09-30 devnull * Write a pixel to img at point pt.
876 76193d7c 2003-09-30 devnull *
877 76193d7c 2003-09-30 devnull * We do this by reading a 32-bit little endian
878 76193d7c 2003-09-30 devnull * value from p and then writing it back
879 76193d7c 2003-09-30 devnull * after tweaking the appropriate bits. Because
880 76193d7c 2003-09-30 devnull * the data is little endian, we don't have to worry
881 76193d7c 2003-09-30 devnull * about what the actual depth is, as long as it is
882 76193d7c 2003-09-30 devnull * less than 32 bits.
883 76193d7c 2003-09-30 devnull */
884 76193d7c 2003-09-30 devnull void
885 76193d7c 2003-09-30 devnull putpixel(Memimage *img, Point pt, u32int nv)
886 76193d7c 2003-09-30 devnull {
887 76193d7c 2003-09-30 devnull uchar r, g, b, a, *p, *q;
888 76193d7c 2003-09-30 devnull u32int c, mask, bits, v;
889 76193d7c 2003-09-30 devnull int bpp, sh, npack, nbits;
890 76193d7c 2003-09-30 devnull
891 76193d7c 2003-09-30 devnull pixtorgba(nv, &r, &g, &b, &a);
892 76193d7c 2003-09-30 devnull
893 76193d7c 2003-09-30 devnull p = byteaddr(img, pt);
894 76193d7c 2003-09-30 devnull v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
895 76193d7c 2003-09-30 devnull bpp = img->depth;
896 76193d7c 2003-09-30 devnull DBG print("v %.8lux...", v);
897 76193d7c 2003-09-30 devnull if(bpp < 8){
898 76193d7c 2003-09-30 devnull /*
899 76193d7c 2003-09-30 devnull * Sub-byte greyscale pixels. We need to skip the leftmost pt.x%npack pixels,
900 76193d7c 2003-09-30 devnull * which is equivalent to skipping the rightmost npack - pt.x%npack - 1 pixels.
901 76193d7c 2003-09-30 devnull */
902 76193d7c 2003-09-30 devnull npack = 8/bpp;
903 76193d7c 2003-09-30 devnull sh = bpp*(npack - pt.x%npack - 1);
904 76193d7c 2003-09-30 devnull bits = RGB2K(r,g,b);
905 76193d7c 2003-09-30 devnull DBG print("repl %lux 8 %d = %lux...", bits, bpp, replbits(bits, 8, bpp));
906 76193d7c 2003-09-30 devnull bits = replbits(bits, 8, bpp);
907 76193d7c 2003-09-30 devnull mask = (1<<bpp)-1;
908 76193d7c 2003-09-30 devnull DBG print("bits %lux mask %lux sh %d...", bits, mask, sh);
909 76193d7c 2003-09-30 devnull mask <<= sh;
910 76193d7c 2003-09-30 devnull bits <<= sh;
911 76193d7c 2003-09-30 devnull DBG print("(%lux & %lux) | (%lux & %lux)", v, ~mask, bits, mask);
912 76193d7c 2003-09-30 devnull v = (v & ~mask) | (bits & mask);
913 76193d7c 2003-09-30 devnull } else {
914 76193d7c 2003-09-30 devnull /*
915 76193d7c 2003-09-30 devnull * General case. We need to parse the channel descriptor again.
916 76193d7c 2003-09-30 devnull */
917 76193d7c 2003-09-30 devnull sh = 0;
918 76193d7c 2003-09-30 devnull for(c=img->chan; c; c>>=8){
919 76193d7c 2003-09-30 devnull nbits = NBITS(c);
920 76193d7c 2003-09-30 devnull switch(TYPE(c)){
921 76193d7c 2003-09-30 devnull case CRed:
922 76193d7c 2003-09-30 devnull bits = r;
923 76193d7c 2003-09-30 devnull break;
924 76193d7c 2003-09-30 devnull case CGreen:
925 76193d7c 2003-09-30 devnull bits = g;
926 76193d7c 2003-09-30 devnull break;
927 76193d7c 2003-09-30 devnull case CBlue:
928 76193d7c 2003-09-30 devnull bits = b;
929 76193d7c 2003-09-30 devnull break;
930 76193d7c 2003-09-30 devnull case CGrey:
931 76193d7c 2003-09-30 devnull bits = RGB2K(r, g, b);
932 76193d7c 2003-09-30 devnull break;
933 76193d7c 2003-09-30 devnull case CAlpha:
934 76193d7c 2003-09-30 devnull bits = a;
935 76193d7c 2003-09-30 devnull break;
936 76193d7c 2003-09-30 devnull case CIgnore:
937 76193d7c 2003-09-30 devnull bits = 0;
938 76193d7c 2003-09-30 devnull break;
939 76193d7c 2003-09-30 devnull case CMap:
940 76193d7c 2003-09-30 devnull q = img->cmap->rgb2cmap;
941 76193d7c 2003-09-30 devnull bits = q[(r>>4)*16*16+(g>>4)*16+(b>>4)];
942 76193d7c 2003-09-30 devnull break;
943 76193d7c 2003-09-30 devnull default:
944 76193d7c 2003-09-30 devnull SET(bits);
945 76193d7c 2003-09-30 devnull fprint(2, "unknown channel type %lud\n", TYPE(c));
946 76193d7c 2003-09-30 devnull abort();
947 76193d7c 2003-09-30 devnull }
948 76193d7c 2003-09-30 devnull
949 76193d7c 2003-09-30 devnull DBG print("repl %lux 8 %d = %lux...", bits, nbits, replbits(bits, 8, nbits));
950 76193d7c 2003-09-30 devnull if(TYPE(c) != CMap)
951 76193d7c 2003-09-30 devnull bits = replbits(bits, 8, nbits);
952 76193d7c 2003-09-30 devnull mask = (1<<nbits)-1;
953 76193d7c 2003-09-30 devnull DBG print("bits %lux mask %lux sh %d...", bits, mask, sh);
954 76193d7c 2003-09-30 devnull bits <<= sh;
955 76193d7c 2003-09-30 devnull mask <<= sh;
956 76193d7c 2003-09-30 devnull v = (v & ~mask) | (bits & mask);
957 76193d7c 2003-09-30 devnull sh += nbits;
958 76193d7c 2003-09-30 devnull }
959 76193d7c 2003-09-30 devnull }
960 76193d7c 2003-09-30 devnull DBG print("v %.8lux\n", v);
961 76193d7c 2003-09-30 devnull p[0] = v;
962 76193d7c 2003-09-30 devnull p[1] = v>>8;
963 76193d7c 2003-09-30 devnull p[2] = v>>16;
964 76193d7c 2003-09-30 devnull p[3] = v>>24;
965 76193d7c 2003-09-30 devnull }
966 76193d7c 2003-09-30 devnull #undef DBG
967 76193d7c 2003-09-30 devnull
968 76193d7c 2003-09-30 devnull #define DBG if(0)
969 76193d7c 2003-09-30 devnull void
970 76193d7c 2003-09-30 devnull drawonepixel(Memimage *dst, Point dp, Memimage *src, Point sp, Memimage *mask, Point mp)
971 76193d7c 2003-09-30 devnull {
972 76193d7c 2003-09-30 devnull uchar m, M, sr, sg, sb, sa, sk, dr, dg, db, da, dk;
973 76193d7c 2003-09-30 devnull
974 76193d7c 2003-09-30 devnull pixtorgba(getpixel(dst, dp), &dr, &dg, &db, &da);
975 76193d7c 2003-09-30 devnull pixtorgba(getpixel(src, sp), &sr, &sg, &sb, &sa);
976 76193d7c 2003-09-30 devnull m = getmask(mask, mp);
977 76193d7c 2003-09-30 devnull M = 255-(sa*m)/255;
978 76193d7c 2003-09-30 devnull
979 76193d7c 2003-09-30 devnull DBG print("dst %x %x %x %x src %x %x %x %x m %x = ", dr,dg,db,da, sr,sg,sb,sa, m);
980 76193d7c 2003-09-30 devnull if(dst->flags&Fgrey){
981 76193d7c 2003-09-30 devnull /*
982 76193d7c 2003-09-30 devnull * We need to do the conversion to grey before the alpha calculation
983 76193d7c 2003-09-30 devnull * because the draw operator does this, and we need to be operating
984 76193d7c 2003-09-30 devnull * at the same precision so we get exactly the same answers.
985 76193d7c 2003-09-30 devnull */
986 76193d7c 2003-09-30 devnull sk = RGB2K(sr, sg, sb);
987 76193d7c 2003-09-30 devnull dk = RGB2K(dr, dg, db);
988 76193d7c 2003-09-30 devnull dk = (sk*m + dk*M)/255;
989 76193d7c 2003-09-30 devnull dr = dg = db = dk;
990 76193d7c 2003-09-30 devnull da = (sa*m + da*M)/255;
991 76193d7c 2003-09-30 devnull }else{
992 76193d7c 2003-09-30 devnull /*
993 76193d7c 2003-09-30 devnull * True color alpha calculation treats all channels (including alpha)
994 76193d7c 2003-09-30 devnull * the same. It might have been nice to use an array, but oh well.
995 76193d7c 2003-09-30 devnull */
996 76193d7c 2003-09-30 devnull dr = (sr*m + dr*M)/255;
997 76193d7c 2003-09-30 devnull dg = (sg*m + dg*M)/255;
998 76193d7c 2003-09-30 devnull db = (sb*m + db*M)/255;
999 76193d7c 2003-09-30 devnull da = (sa*m + da*M)/255;
1000 76193d7c 2003-09-30 devnull }
1001 76193d7c 2003-09-30 devnull
1002 76193d7c 2003-09-30 devnull DBG print("%x %x %x %x\n", dr,dg,db,da);
1003 76193d7c 2003-09-30 devnull putpixel(dst, dp, rgbatopix(dr, dg, db, da));
1004 76193d7c 2003-09-30 devnull }