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

📄 draw.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
		off = pt.x%npack;		val = p[0] >> bpp*(npack-1-off);		val &= (1<<bpp)-1;		break;	case 8:		val = p[0];		break;	case 16:		val = p[0]|(p[1]<<8);		break;	case 24:		val = p[0]|(p[1]<<8)|(p[2]<<16);		break;	case 32:		val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);		break;	}	while(bpp<32){		val |= val<<bpp;		bpp *= 2;	}	return val;}static Calcfn*boolcopyfn(Memimage *img, Memimage *mask){	if(mask->flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0)		return boolmemmove;	switch(img->depth){	case 8:		return boolcopy8;	case 16:		return boolcopy16;	case 24:		return boolcopy24;	case 32:		return boolcopy32;	default:		assert(0 /* boolcopyfn */);	}	return nil;}/* * Optimized draw for filling and scrolling; uses memset and memmove. */static voidmemsetb(void *vp, uchar val, int n){	uchar *p, *ep;	p = vp;	ep = p+n;	while(p<ep)		*p++ = val;}static voidmemsets(void *vp, ushort val, int n){	ushort *p, *ep;	p = vp;	ep = p+n;	while(p<ep)		*p++ = val;}static voidmemsetl(void *vp, ulong val, int n){	ulong *p, *ep;	p = vp;	ep = p+n;	while(p<ep)		*p++ = val;}static voidmemset24(void *vp, ulong val, int n){	uchar *p, *ep;	uchar a,b,c;	p = vp;	ep = p+3*n;	a = val;	b = val>>8;	c = val>>16;	while(p<ep){		*p++ = a;		*p++ = b;		*p++ = c;	}}static ulongimgtorgba(Memimage *img, ulong val){	uchar r, g, b, a;	int nb, ov, v;	ulong chan;	uchar *p;	a = 0xFF;	r = g = b = 0xAA;	/* garbage */	for(chan=img->chan; chan; chan>>=8){		nb = NBITS(chan);		ov = v = val&((1<<nb)-1);		val >>= nb;		while(nb < 8){			v |= v<<nb;			nb *= 2;		}		v >>= (nb-8);		switch(TYPE(chan)){		case CRed:			r = v;			break;		case CGreen:			g = v;			break;		case CBlue:			b = v;			break;		case CAlpha:			a = v;			break;		case CGrey:			r = g = b = v;			break;		case CMap:			p = img->cmap->cmap2rgb+3*ov;			r = *p++;			g = *p++;				b = *p;			break;		}	}	return (r<<24)|(g<<16)|(b<<8)|a;	}static ulongrgbatoimg(Memimage *img, ulong rgba){	ulong chan;	int d, nb;	ulong v;	uchar *p, r, g, b, a, m;	v = 0;	r = rgba>>24;	g = rgba>>16;	b = rgba>>8;	a = rgba;	d = 0;	for(chan=img->chan; chan; chan>>=8){		nb = NBITS(chan);		switch(TYPE(chan)){		case CRed:			v |= (r>>(8-nb))<<d;			break;		case CGreen:			v |= (g>>(8-nb))<<d;			break;		case CBlue:			v |= (b>>(8-nb))<<d;			break;		case CAlpha:			v |= (a>>(8-nb))<<d;			break;		case CMap:			p = img->cmap->rgb2cmap;			m = p[(r>>4)*256+(g>>4)*16+(b>>4)];			v |= (m>>(8-nb))<<d;			break;		case CGrey:			m = RGB2K(r,g,b);			v |= (m>>(8-nb))<<d;			break;		}		d += nb;	}//	print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v);	return v;}#define DBG if(0)static intmemoptdraw(Memdrawparam *par){	int m, y, dy, dx, op;	ulong v;	Memimage *src;	Memimage *dst;	dx = Dx(par->r);	dy = Dy(par->r);	src = par->src;	dst = par->dst;	op = par->op;DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth);	/*	 * If we have an opaque mask and source is one opaque pixel we can convert to the	 * destination format and just replicate with memset.	 */	m = Simplesrc|Simplemask|Fullmask;	if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){		uchar *dp, p[4];		int d, dwid, ppb, np, nb;		uchar lm, rm;DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata);		dwid = dst->width*sizeof(ulong);		dp = byteaddr(dst, par->r.min);		v = par->sdval;DBG print("sdval %lud, depth %d\n", v, dst->depth);		switch(dst->depth){		case 1:		case 2:		case 4:			for(d=dst->depth; d<8; d*=2)				v |= (v<<d);			ppb = 8/dst->depth;	/* pixels per byte */			m = ppb-1;			/* left edge */			np = par->r.min.x&m;		/* no. pixels unused on left side of word */			dx -= (ppb-np);			nb = 8 - np * dst->depth;		/* no. bits used on right side of word */			lm = (1<<nb)-1;DBG print("np %d x %d nb %d lm %ux ppb %d m %ux\n", np, par->r.min.x, nb, lm, ppb, m);				/* right edge */			np = par->r.max.x&m;	/* no. pixels used on left side of word */			dx -= np;			nb = 8 - np * dst->depth;		/* no. bits unused on right side of word */			rm = ~((1<<nb)-1);DBG print("np %d x %d nb %d rm %ux ppb %d m %ux\n", np, par->r.max.x, nb, rm, ppb, m);	DBG print("dx %d Dx %d\n", dx, Dx(par->r));			/* lm, rm are masks that are 1 where we should touch the bits */			if(dx < 0){	/* just one byte */				lm &= rm;				for(y=0; y<dy; y++, dp+=dwid)					*dp ^= (v ^ *dp) & lm;			}else if(dx == 0){	/* no full bytes */				if(lm)					dwid--;				for(y=0; y<dy; y++, dp+=dwid){					if(lm){DBG print("dp %p v %lux lm %ux (v ^ *dp) & lm %lux\n", dp, v, lm, (v^*dp)&lm);						*dp ^= (v ^ *dp) & lm;						dp++;					}					*dp ^= (v ^ *dp) & rm;				}			}else{		/* full bytes in middle */				dx /= ppb;				if(lm)					dwid--;				dwid -= dx;				for(y=0; y<dy; y++, dp+=dwid){					if(lm){						*dp ^= (v ^ *dp) & lm;						dp++;					}					memset(dp, v, dx);					dp += dx;					*dp ^= (v ^ *dp) & rm;				}			}			return 1;		case 8:			for(y=0; y<dy; y++, dp+=dwid)				memset(dp, v, dx);			return 1;		case 16:			p[0] = v;		/* make little endian */			p[1] = v>>8;			v = *(ushort*)p;DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n",	dp, dx, dy, dwid);			for(y=0; y<dy; y++, dp+=dwid)				memsets(dp, v, dx);			return 1;		case 24:			for(y=0; y<dy; y++, dp+=dwid)				memset24(dp, v, dx);			return 1;		case 32:			p[0] = v;		/* make little endian */			p[1] = v>>8;			p[2] = v>>16;			p[3] = v>>24;			v = *(ulong*)p;			for(y=0; y<dy; y++, dp+=dwid)				memsetl(dp, v, dx);			return 1;		default:			assert(0 /* bad dest depth in memoptdraw */);		}	}	/*	 * If no source alpha, an opaque mask, we can just copy the	 * source onto the destination.  If the channels are the same and	 * the source is not replicated, memmove suffices.	 */	m = Simplemask|Fullmask;	if((par->state&(m|Replsrc))==m && src->depth >= 8 	&& src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){		uchar *sp, *dp;		long swid, dwid, nb;		int dir;		if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min))			dir = -1;		else			dir = 1;		swid = src->width*sizeof(ulong);		dwid = dst->width*sizeof(ulong);		sp = byteaddr(src, par->sr.min);		dp = byteaddr(dst, par->r.min);		if(dir == -1){			sp += (dy-1)*swid;			dp += (dy-1)*dwid;			swid = -swid;			dwid = -dwid;		}		nb = (dx*src->depth)/8;		for(y=0; y<dy; y++, sp+=swid, dp+=dwid)			memmove(dp, sp, nb);		return 1;	}	/*	 * If we have a 1-bit mask, 1-bit source, and 1-bit destination, and	 * they're all bit aligned, we can just use bit operators.  This happens	 * when we're manipulating boolean masks, e.g. in the arc code.	 */	if((par->state&(Simplemask|Simplesrc|Replmask|Replsrc))==0 	&& dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1 	&& (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){		uchar *sp, *dp, *mp;		uchar lm, rm;		long swid, dwid, mwid;		int i, x, dir;		sp = byteaddr(src, par->sr.min);		dp = byteaddr(dst, par->r.min);		mp = byteaddr(par->mask, par->mr.min);		swid = src->width*sizeof(ulong);		dwid = dst->width*sizeof(ulong);		mwid = par->mask->width*sizeof(ulong);		if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){			dir = -1;		}else			dir = 1;		lm = 0xFF>>(par->r.min.x&7);		rm = 0xFF<<(8-(par->r.max.x&7));		dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7);		if(dx < 0){	/* one byte wide */			lm &= rm;			if(dir == -1){				dp += dwid*(dy-1);				sp += swid*(dy-1);				mp += mwid*(dy-1);				dwid = -dwid;				swid = -swid;				mwid = -mwid;			}			for(y=0; y<dy; y++){				*dp ^= (*dp ^ *sp) & *mp & lm;				dp += dwid;				sp += swid;				mp += mwid;			}			return 1;		}		dx /= 8;		if(dir == 1){			i = (lm!=0)+dx+(rm!=0);			mwid -= i;			swid -= i;			dwid -= i;			for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){				if(lm){					*dp ^= (*dp ^ *sp++) & *mp++ & lm;					dp++;				}				for(x=0; x<dx; x++){					*dp ^= (*dp ^ *sp++) & *mp++;					dp++;				}				if(rm){					*dp ^= (*dp ^ *sp++) & *mp++ & rm;					dp++;				}			}			return 1;		}else{		/* dir == -1 */			i = (lm!=0)+dx+(rm!=0);			dp += dwid*(dy-1)+i-1;			sp += swid*(dy-1)+i-1;			mp += mwid*(dy-1)+i-1;			dwid = -dwid+i;			swid = -swid+i;			mwid = -mwid+i;			for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){				if(rm){					*dp ^= (*dp ^ *sp--) & *mp-- & rm;					dp--;				}				for(x=0; x<dx; x++){					*dp ^= (*dp ^ *sp--) & *mp--;					dp--;				}				if(lm){					*dp ^= (*dp ^ *sp--) & *mp-- & lm;					dp--;				}			}		}		return 1;	}	return 0;	}#undef DBG/* * Boolean character drawing. * Solid opaque color through a 1-bit greyscale mask. */#define DBG if(0)static intchardraw(Memdrawparam *par){	ulong bits;	int i, ddepth, dy, dx, x, bx, ex, y, npack, bsh, depth, op;	ulong v, maskwid, dstwid;	uchar *wp, *rp, *q, *wc;	ushort *ws;	ulong *wl;	uchar sp[4];	Rectangle r, mr;	Memimage *mask, *src, *dst;if(0) if(drawdebug) iprint("chardraw? mf %lux md %d sf %lux dxs %d dys %d dd %d ddat %p sdat %p\n",		par->mask->flags, par->mask->depth, par->src->flags, 		Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data);	mask = par->mask;	src = par->src;	dst = par->dst;	r = par->r;	mr = par->mr;	op = par->op;	if((par->state&(Replsrc|Simplesrc|Replmask)) != (Replsrc|Simplesrc)	|| mask->depth != 1 || src->flags&Falpha || dst->depth<8 || dst->data==src->data	|| op != SoverD)		return 0;//if(drawdebug) iprint("chardraw...");	depth = mask->depth;	maskwid = mask->width*sizeof(ulong);	rp = byteaddr(mask, mr.min);	npack = 8/depth;	bsh = (mr.min.x % npack) * depth;	wp = byteaddr(dst, r.min);	dstwid = dst->width*sizeof(ulong);DBG print("bsh %d\n", bsh);	dy = Dy(r);	dx = Dx(r);	ddepth = dst->depth;	/*	 * for loop counts from bsh to bsh+dx	 *	 * we want the bottom bits to be the amount	 * to shift the pixels down, so for n≡0 (mod 8) we want 	 * bottom bits 7.  for n≡1, 6, etc.	 * the bits come from -n-1.	 */	bx = -bsh-1;	ex = -bsh-1-dx;	SET(bits);	v = par->sdval;	/* make little endian */	sp[0] = v;	sp[1] = v>>8;	sp[2] = v>>16;	sp[3] = v>>24;//print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]);	for(y=0; y<dy; y++, rp+=maskwid, wp+=dstwid){		q = rp;		if(bsh)			bits = *q++;		switch(ddepth){		case 8://if(drawdebug) iprint("8loop...");			wc = wp;			for(x=bx; x>ex; x--, wc++){				i = x&7;				if(i == 8-1)					bits = *q++;DBG print("bits %lux sh %d...", bits, i);				if((bits>>i)&1)					*wc = v;			}			break;		case 16:			ws = (ushort*)wp;			v = *(ushort*)sp;			for(x=bx; x>ex; x--, ws++){				i = x&7;				if(i == 8-1)					bits = *q++;DBG print("bits %lux sh %d...", bits, i);				if((bits>>i)&1)					*ws = v;			}			break;		case 24:			wc = wp;			for(x=bx; x>ex; x--, wc+=3){				i = x&7;				if(i == 8-1)					bits = *q++;DBG print("bits %lux sh %d...", bits, i);				if((bits>>i)&1){					wc[0] = sp[0];					wc[1] = sp[1];					wc[2] = sp[2];				}			}			break;		case 32:			wl = (ulong*)wp;			v = *(ulong*)sp;			for(x=bx; x>ex; x--, wl++){				i = x&7;				if(i == 8-1)					bits = *q++;DBG iprint("bits %lux sh %d...", bits, i);				if((bits>>i)&1)					*wl = v;			}			break;		}	}DBG print("\n");		return 1;	}#undef DBG/* * Fill entire byte with replicated (if necessary) copy of source pixel, * assuming destination ldepth is >= source ldepth. * * This code is just plain wrong for >8bpp. *ulongmembyteval(Memimage *src){	int i, val, bpp;	uchar uc;	unloadmemimage(src, src->r, &uc, 1);	bpp = src->depth;	uc <<= (src->r.min.x&(7/src->depth))*src->depth;	uc &= ~(0xFF>>bpp);	/* pixel value is now in high part of byte. repeat throughout byte 	val = uc;	for(i=bpp; i<8; i<<=1)		val |= val>>i;	return val;} *  */voidmemfillcolor(Memimage *i, ulong val){	ulong bits;	int d, y;	if(val == DNofill)		return;	bits = rgbatoimg(i, val);	switch(i->depth){	case 24:	/* 24-bit images suck */		for(y=i->r.min.y; y<i->r.max.y; y++)			memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r));		break;	default:	/* 1, 2, 4, 8, 16, 32 */		for(d=i->depth; d<32; d*=2)			bits = (bits << d) | bits;		memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r));		break;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -