Blame


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