📄 drawtest.c
字号:
dr.min.y = nrand(Yrange-1); dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x); dr.max.y = dr.min.y + 1 + nrand(Yrange-1-dr.min.y); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); tp = sp; up = mp; for(y=dr.min.y; y<dr.max.y && tp.y<Yrange && up.y<Yrange; y++,tp.y++,up.y++){ for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++) memimagedraw(dst, Rect(x, y, x+1, y+1), src, tp, mask, up, SoverD); tp.x = sp.x; up.x = mp.x; } memmove(savedstbits, dst->data->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); for(y=0; y<Yrange; y++) checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, nil, nil);}voidverifyrect(void){ int i; /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; i<niters; i++) verifyrectmask(); /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; i<niters; i++) verifyrectmask(); /* random mask */ for(i=0; i<niters; i++){ fill(mask, maskbits); verifyrectmask(); }}Rectanglerandrect(void){ Rectangle r; r.min.x = nrand(Xrange-1); r.min.y = nrand(Yrange-1); r.max.x = r.min.x + 1 + nrand(Xrange-1-r.min.x); r.max.y = r.min.y + 1 + nrand(Yrange-1-r.min.y); return r;}/* * Return coordinate corresponding to x withing range [minx, maxx) */inttilexy(int minx, int maxx, int x){ int sx; sx = (x-minx) % (maxx-minx); if(sx < 0) sx += maxx-minx; return sx+minx;}voidreplicate(Memimage *i, Memimage *tmp){ Rectangle r, r1; int x, y, nb; /* choose the replication window (i->r) */ r.min.x = nrand(Xrange-1); r.min.y = nrand(Yrange-1); /* make it trivial more often than pure chance allows */ switch(lrand()&0){ case 1: r.max.x = r.min.x + 2; r.max.y = r.min.y + 2; if(r.max.x < Xrange && r.max.y < Yrange) break; /* fall through */ case 0: r.max.x = r.min.x + 1; r.max.y = r.min.y + 1; break; default: if(r.min.x+3 >= Xrange) r.max.x = Xrange; else r.max.x = r.min.x+3 + nrand(Xrange-(r.min.x+3)); if(r.min.y+3 >= Yrange) r.max.y = Yrange; else r.max.y = r.min.y+3 + nrand(Yrange-(r.min.y+3)); } assert(r.min.x >= 0); assert(r.max.x <= Xrange); assert(r.min.y >= 0); assert(r.max.y <= Yrange); /* copy from i to tmp so we have just the replicated bits */ nb = tmp->width*sizeof(ulong)*Yrange; memset(tmp->data->bdata, 0, nb); memimagedraw(tmp, r, i, r.min, ones, r.min, SoverD); memmove(i->data->bdata, tmp->data->bdata, nb); /* i is now a non-replicated instance of the replication */ /* replicate it by hand through tmp */ memset(tmp->data->bdata, 0, nb); x = -(tilexy(r.min.x, r.max.x, 0)-r.min.x); for(; x<Xrange; x+=Dx(r)){ y = -(tilexy(r.min.y, r.max.y, 0)-r.min.y); for(; y<Yrange; y+=Dy(r)){ /* set r1 to instance of tile by translation */ r1.min.x = x; r1.min.y = y; r1.max.x = r1.min.x+Dx(r); r1.max.y = r1.min.y+Dy(r); memimagedraw(tmp, r1, i, r.min, ones, r.min, SoverD); } } i->flags |= Frepl; i->r = r; i->clipr = randrect();// fprint(2, "replicate [[%d %d] [%d %d]] [[%d %d][%d %d]]\n", r.min.x, r.min.y, r.max.x, r.max.y,// i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y); tmp->clipr = i->clipr;}/* * Mask is preset; do the rest */voidverifyrectmaskrepl(int srcrepl, int maskrepl){ Point sp, mp, tp, up; Rectangle dr; int x, y; Memimage *s, *m;// print("verfrect %d %d\n", srcrepl, maskrepl); src->flags &= ~Frepl; src->r = Rect(0, 0, Xrange, Yrange); src->clipr = src->r; stmp->flags &= ~Frepl; stmp->r = Rect(0, 0, Xrange, Yrange); stmp->clipr = src->r; mask->flags &= ~Frepl; mask->r = Rect(0, 0, Xrange, Yrange); mask->clipr = mask->r; mtmp->flags &= ~Frepl; mtmp->r = Rect(0, 0, Xrange, Yrange); mtmp->clipr = mask->r; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); if(srcrepl){ replicate(src, stmp); s = stmp; }else s = src; if(maskrepl){ replicate(mask, mtmp); m = mtmp; }else m = mask; dr = randrect(); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange);DBG print("smalldraws\n"); 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++) 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++) memimagedraw(dst, Rect(x, y, x+1, y+1), s, tp, m, up, SoverD); memmove(savedstbits, dst->data->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange);DBG print("bigdraw\n"); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); for(y=0; y<Yrange; y++) checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, srcrepl?stmp:nil, maskrepl?mtmp:nil);}voidverifyrectrepl(int srcrepl, int maskrepl){ int i; /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; i<niters; i++) verifyrectmaskrepl(srcrepl, maskrepl); /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; i<niters; i++) verifyrectmaskrepl(srcrepl, maskrepl); /* random mask */ for(i=0; i<niters; i++){ fill(mask, maskbits); verifyrectmaskrepl(srcrepl, maskrepl); }}/* * Trivial draw implementation. * Color values are passed around as ulongs containing ααRRGGBB *//* * Convert v, which is nhave bits wide, into its nwant bits wide equivalent. * Replicates to widen the value, truncates to narrow it. */ulongreplbits(ulong v, int nhave, int nwant){ v &= (1<<nhave)-1; for(; nhave<nwant; nhave*=2) v |= v<<nhave; v >>= (nhave-nwant); return v & ((1<<nwant)-1);}/* * Decode a pixel into the uchar* values. */voidpixtorgba(ulong v, uchar *r, uchar *g, uchar *b, uchar *a){ *a = v>>24; *r = v>>16; *g = v>>8; *b = v;}/* * Convert uchar channels into ulong pixel. */ulongrgbatopix(uchar r, uchar g, uchar b, uchar a){ return (a<<24)|(r<<16)|(g<<8)|b;}/* * Retrieve the pixel value at pt in the image. */ulonggetpixel(Memimage *img, Point pt){ uchar r, g, b, a, *p; int nbits, npack, bpp; ulong v, c, rbits, bits; r = g = b = 0; a = ~0; /* default alpha is full */ p = byteaddr(img, pt); v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); bpp = img->depth; if(bpp<8){ /* * Sub-byte greyscale pixels. * * We want to throw away the top pt.x%npack pixels and then use the next bpp bits * in the bottom byte of v. This madness is due to having big endian bits * but little endian bytes. */ npack = 8/bpp; v >>= 8 - bpp*(pt.x%npack+1); v &= (1<<bpp)-1; r = g = b = replbits(v, bpp, 8); }else{ /* * General case. We need to parse the channel descriptor and do what it says. * In all channels but the color map, we replicate to 8 bits because that's the * precision that all calculations are done at. * * In the case of the color map, we leave the bits alone, in case a color map * with less than 8 bits of index is used. This is currently disallowed, so it's * sort of silly. */ for(c=img->chan; c; c>>=8){ nbits = NBITS(c); bits = v & ((1<<nbits)-1); rbits = replbits(bits, nbits, 8); v >>= nbits; switch(TYPE(c)){ case CRed: r = rbits; break; case CGreen: g = rbits; break; case CBlue: b = rbits; break; case CGrey: r = g = b = rbits; break; case CAlpha: a = rbits; break; case CMap: p = img->cmap->cmap2rgb + 3*bits; r = p[0]; g = p[1]; b = p[2]; break; case CIgnore: break; default: fprint(2, "unknown channel type %lud\n", TYPE(c)); abort(); } } } return rgbatopix(r, g, b, a);}/* * Return the greyscale equivalent of a pixel. */uchargetgrey(Memimage *img, Point pt){ uchar r, g, b, a; pixtorgba(getpixel(img, pt), &r, &g, &b, &a); return RGB2K(r, g, b);}/* * Return the value at pt in image, if image is interpreted * as a mask. This means the alpha channel if present, else * the greyscale or its computed equivalent. */uchargetmask(Memimage *img, Point pt){ if(img->flags&Falpha) return getpixel(img, pt)>>24; else return getgrey(img, pt);}#undef DBG#define DBG if(0)/* * Write a pixel to img at point pt. * * We do this by reading a 32-bit little endian * value from p and then writing it back * after tweaking the appropriate bits. Because * the data is little endian, we don't have to worry * about what the actual depth is, as long as it is * less than 32 bits. */voidputpixel(Memimage *img, Point pt, ulong nv){ uchar r, g, b, a, *p, *q; ulong c, mask, bits, v; int bpp, sh, npack, nbits; pixtorgba(nv, &r, &g, &b, &a); p = byteaddr(img, pt); v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); bpp = img->depth;DBG print("v %.8lux...", v); if(bpp < 8){ /* * Sub-byte greyscale pixels. We need to skip the leftmost pt.x%npack pixels, * which is equivalent to skipping the rightmost npack - pt.x%npack - 1 pixels. */ npack = 8/bpp; sh = bpp*(npack - pt.x%npack - 1); bits = RGB2K(r,g,b);DBG print("repl %lux 8 %d = %lux...", bits, bpp, replbits(bits, 8, bpp)); bits = replbits(bits, 8, bpp); mask = (1<<bpp)-1;DBG print("bits %lux mask %lux sh %d...", bits, mask, sh); mask <<= sh; bits <<= sh;DBG print("(%lux & %lux) | (%lux & %lux)", v, ~mask, bits, mask); v = (v & ~mask) | (bits & mask); } else { /* * General case. We need to parse the channel descriptor again. */ sh = 0; for(c=img->chan; c; c>>=8){ nbits = NBITS(c); switch(TYPE(c)){ case CRed: bits = r; break; case CGreen: bits = g; break; case CBlue: bits = b; break; case CGrey: bits = RGB2K(r, g, b); break; case CAlpha: bits = a; break; case CIgnore: bits = 0; break; case CMap: q = img->cmap->rgb2cmap; bits = q[(r>>4)*16*16+(g>>4)*16+(b>>4)]; break; default: SET(bits); fprint(2, "unknown channel type %lud\n", TYPE(c)); abort(); }DBG print("repl %lux 8 %d = %lux...", bits, nbits, replbits(bits, 8, nbits)); if(TYPE(c) != CMap) bits = replbits(bits, 8, nbits); mask = (1<<nbits)-1;DBG print("bits %lux mask %lux sh %d...", bits, mask, sh); bits <<= sh; mask <<= sh; v = (v & ~mask) | (bits & mask); sh += nbits; } }DBG print("v %.8lux\n", v); p[0] = v; p[1] = v>>8; p[2] = v>>16; p[3] = v>>24; }#undef DBG#define DBG if(0)voiddrawonepixel(Memimage *dst, Point dp, Memimage *src, Point sp, Memimage *mask, Point mp){ uchar m, M, sr, sg, sb, sa, sk, dr, dg, db, da, dk; pixtorgba(getpixel(dst, dp), &dr, &dg, &db, &da); pixtorgba(getpixel(src, sp), &sr, &sg, &sb, &sa); m = getmask(mask, mp); M = 255-(sa*m)/255;DBG print("dst %x %x %x %x src %x %x %x %x m %x = ", dr,dg,db,da, sr,sg,sb,sa, m); if(dst->flags&Fgrey){ /* * We need to do the conversion to grey before the alpha calculation * because the draw operator does this, and we need to be operating * at the same precision so we get exactly the same answers. */ sk = RGB2K(sr, sg, sb); dk = RGB2K(dr, dg, db); dk = (sk*m + dk*M)/255; dr = dg = db = dk; da = (sa*m + da*M)/255; }else{ /* * True color alpha calculation treats all channels (including alpha) * the same. It might have been nice to use an array, but oh well. */ dr = (sr*m + dr*M)/255; dg = (sg*m + dg*M)/255; db = (sb*m + db*M)/255; da = (sa*m + da*M)/255; }DBG print("%x %x %x %x\n", dr,dg,db,da); putpixel(dst, dp, rgbatopix(dr, dg, db, da));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -