⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drawtest.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -