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

📄 devdraw.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(drawcmp(name->name, str, n) == 0)			error(Enameused);	t = smalloc((sdraw.nname+1)*sizeof(DName));	memmove(t, sdraw.name, sdraw.nname*sizeof(DName));	free(sdraw.name);	sdraw.name = t;	new = &sdraw.name[sdraw.nname++];	new->name = smalloc(n+1);	memmove(new->name, str, n);	new->name[n] = 0;	new->dimage = di;	new->client = client;	new->vers = ++sdraw.vers;}Client*drawnewclient(void){	Client *cl, **cp;	int i;	for(i=0; i<sdraw.nclient; i++){		cl = sdraw.client[i];		if(cl == 0)			break;	}	if(i == sdraw.nclient){		cp = malloc((sdraw.nclient+1)*sizeof(Client*));		if(cp == 0)			return 0;		memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));		free(sdraw.client);		sdraw.client = cp;		sdraw.nclient++;		cp[i] = 0;	}	cl = malloc(sizeof(Client));	if(cl == 0)		return 0;	memset(cl, 0, sizeof(Client));	cl->slot = i;	cl->clientid = ++sdraw.clientid;	cl->op = SoverD;	sdraw.client[i] = cl;	return cl;}static intdrawclientop(Client *cl){	int op;	op = cl->op;	cl->op = SoverD;	return op;}intdrawhasclients(void){	/*	 * if draw has ever been used, we can't resize the frame buffer,	 * even if all clients have exited (nclients is cumulative); it's too	 * hard to make work.	 */	return sdraw.nclient != 0;}Client*drawclientofpath(ulong path){	Client *cl;	int slot;	slot = CLIENTPATH(path);	if(slot == 0)		return nil;	cl = sdraw.client[slot-1];	if(cl==0 || cl->clientid==0)		return nil;	return cl;}Client*drawclient(Chan *c){	Client *client;	client = drawclientofpath(c->qid.path);	if(client == nil)		error(Enoclient);	return client;}Memimage*drawimage(Client *client, uchar *a){	DImage *d;	d = drawlookup(client, BGLONG(a), 1);	if(d == nil)		error(Enodrawimage);	return d->image;}voiddrawrectangle(Rectangle *r, uchar *a){	r->min.x = BGLONG(a+0*4);	r->min.y = BGLONG(a+1*4);	r->max.x = BGLONG(a+2*4);	r->max.y = BGLONG(a+3*4);}voiddrawpoint(Point *p, uchar *a){	p->x = BGLONG(a+0*4);	p->y = BGLONG(a+1*4);}Pointdrawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op){	FChar *fc;	Rectangle r;	Point sp1;	static Memimage *tmp;	fc = &font->fchar[index];	r.min.x = p.x+fc->left;	r.min.y = p.y-(font->ascent-fc->miny);	r.max.x = r.min.x+(fc->maxx-fc->minx);	r.max.y = r.min.y+(fc->maxy-fc->miny);	sp1.x = sp->x+fc->left;	sp1.y = sp->y+fc->miny;	/*	 * If we're drawing greyscale fonts onto a VGA screen,	 * it's very costly to read the screen memory to do the	 * alpha blending inside memdraw.  If this is really a stringbg,	 * then rdst is the bg image (in main memory) which we can	 * refer to for the underlying dst pixels instead of reading dst	 * directly.	 */	if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){		if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){			if(tmp)				freememimage(tmp);			tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);			if(tmp == nil)				goto fallback;		}		memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);		memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);		memdraw(dst, r, tmp, ZP, memopaque, ZP, S);	}else{	fallback:		memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);	}	p.x += fc->width;	sp->x += fc->width;	return p;}static DImage*makescreenimage(void){	void *X;	int width, depth;	ulong chan;	DImage *di;	Memdata *md;	Memimage *i;	Rectangle r;	md = malloc(sizeof *md);	if(md == nil)		return nil;	md->allocd = 1;	md->base = nil;	md->bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen, &X);	if(md->bdata == nil){		free(md);		return nil;	}	md->ref = 1;	i = allocmemimaged(r, chan, md, X);	if(i == nil){		free(md);		return nil;	}	i->width = width;	i->clipr = r;	di = allocdimage(i);	if(di == nil){		freememimage(i);	/* frees md */		return nil;	}	if(!waserror()){		snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);		drawaddname(nil, di, strlen(screenname), screenname);		poperror();	}	return di;}voiddrawreplacescreenimage(Memimage *m){	int i;	DImage *di;	if(screendimage == nil)		return;	/*	 * Replace the screen image because the screen	 * was resized.  Clients still have references to the	 * old screen image, so we can't free it just yet.	 */	drawqlock();	di = allocdimage(m);	if(di == nil){		print("no memory to replace screen image\n");		freememimage(m);		drawqunlock();		return;	}		/* Replace old screen image in global name lookup. */	for(i=0; i<sdraw.nname; i++){		if(sdraw.name[i].dimage == screendimage)		if(sdraw.name[i].client == nil){			sdraw.name[i].dimage = di;			break;		}	}	drawfreedimage(screendimage);	screendimage = di;	screenimage = m;	/*	 * Every client, when it starts, gets a copy of the	 * screen image as image 0.  Clients only use it 	 * for drawing if there is no /dev/winname, but	 * this /dev/draw provides a winname (early ones	 * didn't; winname originated in rio), so the	 * image only ends up used to find the screen	 * resolution and pixel format during initialization.	 * Silently remove the now-outdated image 0s.	 */	for(i=0; i<sdraw.nclient; i++){		if(sdraw.client[i] && !waserror()){			drawuninstall(sdraw.client[i], 0);			poperror();		}	}	drawqunlock();	mouseresize();}static intinitscreenimage(void){	if(screenimage != nil)		return 1;	screendimage = makescreenimage();	if(screendimage == nil)		return 0;	screenimage = screendimage->image;// iprint("initscreenimage %p %p\n", screendimage, screenimage);	mouseresize();	return 1;}voiddeletescreenimage(void){	drawqlock();	if(screenimage){		/* will be freed via screendimage; disable */		screenimage->clipr = ZR;		screenimage = nil;	}	if(screendimage){		drawfreedimage(screendimage);		screendimage = nil;	}	drawqunlock();}voidresetscreenimage(void){	drawqlock();	initscreenimage();	drawqunlock();}static Chan*drawattach(char *spec){	drawqlock();	if(!conf.monitor || !initscreenimage()){		drawqunlock();		error("no frame buffer");	}	drawqunlock();	return devattach('i', spec);}static Walkqid*drawwalk(Chan *c, Chan *nc, char **name, int nname){	if(screenimage == nil)		error("no frame buffer");	return devwalk(c, nc, name, nname, 0, 0, drawgen);}static intdrawstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, 0, 0, drawgen);}static Chan*drawopen(Chan *c, int omode){	Client *cl;	DName *dn;	DImage *di;	if(c->qid.type & QTDIR){		c = devopen(c, omode, 0, 0, drawgen);		c->iounit = IOUNIT;	}	drawqlock();	if(waserror()){		drawqunlock();		nexterror();	}	if(QID(c->qid) == Qnew){		cl = drawnewclient();		if(cl == 0)			error(Enodev);		c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);	}	switch(QID(c->qid)){	case Qwinname:		break;	case Qnew:		break;	case Qctl:		cl = drawclient(c);		if(cl->busy)			error(Einuse);		cl->busy = 1;		flushrect = Rect(10000, 10000, -10000, -10000);		dn = drawlookupname(strlen(screenname), screenname);		if(dn == 0)			error("draw: cannot happen 2");		if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)			error(Edrawmem);		di = drawlookup(cl, 0, 0);		if(di == 0)			error("draw: cannot happen 1");		di->vers = dn->vers;		di->name = smalloc(strlen(screenname)+1);		strcpy(di->name, screenname);		di->fromname = dn->dimage;		di->fromname->ref++;		incref(&cl->r);		break;	case Qcolormap:	case Qdata:	case Qrefresh:		cl = drawclient(c);		incref(&cl->r);		break;	}	drawqunlock();	poperror();	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	c->iounit = IOUNIT;	return c;}static voiddrawclose(Chan *c){	int i;	DImage *d, **dp;	Client *cl;	Refresh *r;	if(QID(c->qid) < Qcolormap)	/* Qtopdir, Qnew, Q3rd, Q2nd have no client */		return;	drawqlock();	if(waserror()){		drawqunlock();		nexterror();	}	cl = drawclient(c);	if(QID(c->qid) == Qctl)		cl->busy = 0;	if((c->flag&COPEN) && (decref(&cl->r)==0)){		while((r = cl->refresh)){	/* assign = */			cl->refresh = r->next;			free(r);		}		/* free names */		for(i=0; i<sdraw.nname; )			if(sdraw.name[i].client == cl)				drawdelname(sdraw.name+i);			else				i++;		while(cl->cscreen)			drawuninstallscreen(cl, cl->cscreen);		/* all screens are freed, so now we can free images */		dp = cl->dimage;		for(i=0; i<NHASH; i++){			while((d = *dp) != nil){				*dp = d->next;				drawfreedimage(d);			}			dp++;		}		sdraw.client[cl->slot] = 0;		drawflush();	/* to erase visible, now dead windows */		free(cl);	}	drawqunlock();	poperror();}longdrawread(Chan *c, void *a, long n, vlong off){	int index, m;	ulong red, green, blue;	Client *cl;	uchar *p;	Refresh *r;	DImage *di;	Memimage *i;	ulong offset = off;	char buf[16];	if(c->qid.type & QTDIR)		return devdirread(c, a, n, 0, 0, drawgen);	if(QID(c->qid) == Qwinname)		return readstr(off, a, n, screenname);	cl = drawclient(c);	drawqlock();	if(waserror()){		drawqunlock();		nexterror();	}	switch(QID(c->qid)){	case Qctl:		if(n < 12*12)			error(Eshortread);		if(cl->infoid < 0)			error(Enodrawimage);		if(cl->infoid == 0){			i = screenimage;			if(i == nil)				error(Enodrawimage);		}else{			di = drawlookup(cl, cl->infoid, 1);			if(di == nil)				error(Enodrawimage);			i = di->image;		}		n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",			cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,			i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,			i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);		cl->infoid = -1;		break;	case Qcolormap:		drawactive(1);	/* to restore map from backup */		p = malloc(4*12*256+1);		if(p == 0)			error(Enomem);		m = 0;		for(index = 0; index < 256; index++){			getcolor(index, &red, &green, &blue);			m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24);		}		n = readstr(offset, a, n, (char*)p);		free(p);		break;	case Qdata:		if(cl->readdata == nil)			error("no draw data");		if(n < cl->nreaddata)			error(Eshortread);		n = cl->nreaddata;		memmove(a, cl->readdata, cl->nreaddata);		free(cl->readdata);		cl->readdata = nil;		break;	case Qrefresh:		if(n < 5*4)			error(Ebadarg);		for(;;){			if(cl->refreshme || cl->refresh)				break;			drawqunlock();			if(waserror()){				drawqlock();	/* restore lock for waserror() above */				nexterror();			}			sleep(&cl->refrend, drawrefactive, cl);			poperror();			drawqlock();		}		p = a;		while(cl->refresh && n>=5*4){			r = cl->refresh;			BPLONG(p+0*4, r->dimage->id);			BPLONG(p+1*4, r->r.min.x);			BPLONG(p+2*4, r->r.min.y);			BPLONG(p+3*4, r->r.max.x);			BPLONG(p+4*4, r->r.max.y);			cl->refresh = r->next;			free(r);			p += 5*4;			n -= 5*4;		}		cl->refreshme = 0;		n = p-(uchar*)a;		break;	}	drawqunlock();	poperror();	return n;}voiddrawwakeall(void){	Client *cl;	int i;	for(i=0; i<sdraw.nclient; i++){		cl = sdraw.client[i];		if(cl && (cl->refreshme || cl->refresh))			wakeup(&cl->refrend);	}}static longdrawwrite(Chan *c, void *a, long n, vlong _){	char buf[128], *fields[4], *q;	Client *cl;	int i, m, red, green, blue, x;	if(c->qid.type & QTDIR)		error(Eisdir);	cl = drawclient(c);	drawqlock();	if(waserror()){		drawwakeall();		drawqunlock();		nexterror();	}	switch(QID(c->qid)){	case Qctl:		if(n != 4)			error("unknown draw control request");		cl->infoid = BGLONG((uchar*)a);		break;	case Qcolormap:		drawactive(1);	/* to restore map from backup */		m = n;		n = 0;		while(m > 0){			x = m;			if(x > sizeof(buf)-1)				x = sizeof(buf)-1;			q = memccpy(buf, a, '\n', x);			if(q == 0)				break;			i = q-buf;			n += i;			a = (char*)a + i;			m -= i;			*q = 0;			if(tokenize(buf, fields, nelem(fields)) != 4)				error(Ebadarg);			i = strtoul(fields[0], 0, 0);			red = strtoul(fields[1], 0, 0);			green = strtoul(fields[2], 0, 0);			blue = strtoul(fields[3], &q, 0);			if(fields[3] == q)				error(Ebadarg);			if(red>255 || green>255 || blue>255 || i<0 || i>255)				error(Ebadarg);			red |= red<<8;			red |= red<<16;			green |= green<<8;			green |= green<<16;			blue |= blue<<8;			blue |= blue<<16;			setcolor(i, red, green, blue);		}		break;	case Qdata:		drawmesg(cl, a, n);		drawwakeall();		break;	default:		error(Ebadusefd);	}	drawqunlock();	poperror();	return n;}uchar*drawcoord(uchar *p, uchar *maxp, int oldx, int *newx){	int b, x;	if(p >= maxp)		error(Eshortdraw);	b = *p++;	x = b & 0x7F;	if(b & 0x80){		if(p+1 >= maxp)			error(Eshortdraw);		x |= *p++ << 7;		x |= *p++ << 15;		if(x & (1<<22))			x |= ~0<<23;	}else{		if(b & 0x40)			x |= ~0<<7;		x += oldx;	}	*newx = x;	return p;}static voidprintmesg(char *fmt, uchar *a, int plsprnt){	char buf[256];	char *p, *q;	if(1|| plsprnt==0){		return;	}	q = buf;	*q++ = *a++;	for(p=fmt; *p; p++){		switch(*p){		case 'l':			q += sprint(q, " %ld", (long)BGLONG(a));			a += 4;			break;		case 'L':			q += sprint(q, " %.8lux", (ulong)BGLONG(a));			a += 4;			break;		case 'R':			q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));			a += 16;			break;		case 'P':			q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));			a += 8;			break;		case 'b':			q += sprint(q, " %d", *a++);			break;		case 's':			q += sprint(q, " %d", BGSHORT(a));			a += 2;			break;		case 'S':			q += sprint(q, " %.4ux", BGSHORT(a));			a += 2;			break;		}	}	*q++ = '\n';	*q = 0;	iprint("%.*s", (int)(q-buf), buf);}voiddrawmesg(Client *client, void *av, int n){	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;	uchar *u, *a, refresh;	char *fmt;	ulong value, chan;	Rectangle r, clipr;	Point p, q, *pp, sp;	Memimage *i, *bg, *dst, *src, *mask;	Memimage *l, **lp;	Memscreen *scrn;	DImage *font, *ll, *di, *ddst, *dsrc;	DName *dn;	DScreen *dscrn;	FChar *fc;	Refx *refx;	CScreen *cs;	Refreshfn reffn;	a = av;	m = 0;	fmt = nil;	if(waserror()){		if(fmt) printmesg(fmt, a, 1);	/*	iprint("error: %s\n", up->errstr);	*/		nexterror();	}	while((n-=m) > 0){		a += m;		switch(*a){		default:			error("bad draw command");		/* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */		case 'b':			printmesg(fmt="LLbLbRRL", a, 0);			m = 1+4+4+1+4+1+4*4+4*4+4;			if(n < m)				error(Eshortdraw);			dstid = BGLONG(a+1);

⌨️ 快捷键说明

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