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

📄 ico.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h>#include <event.h>#include <cursor.h>typedef struct Icon Icon;struct Icon{	Icon	*next;	uchar	w;		/* icon width */	uchar	h;		/* icon height */	ushort	ncolor;		/* number of colors */	ushort	nplane;		/* number of bit planes */	ushort	bits;		/* bits per pixel */	ulong	len;		/* length of data */	ulong	offset;		/* file offset to data */	Image	*img;	Image	*mask;	Rectangle r;		/* relative */	Rectangle sr;		/* abs */};typedef struct Header Header;struct Header{	uint	n;	Icon	*first;	Icon	*last;};int debug;Mouse mouse;Header h;Image *background;ushortgets(uchar *p){	return p[0] | (p[1]<<8);}ulonggetl(uchar *p){	return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);}intBgetheader(Biobuf *b, Header *h){	Icon *icon;	int i;	uchar buf[40];	memset(h, 0, sizeof(*h));	if(Bread(b, buf, 6) != 6)		goto eof;	if(gets(&buf[0]) != 0)		goto header;	if(gets(&buf[2]) != 1)		goto header;	h->n = gets(&buf[4]);	for(i = 0; i < h->n; i++){		icon = mallocz(sizeof(*icon), 1);		if(icon == nil)			sysfatal("malloc: %r");		if(Bread(b, buf, 16) != 16)			goto eof;		icon->w = buf[0];		icon->h = buf[1];		icon->ncolor = buf[2] == 0 ? 256 : buf[2];		if(buf[3] != 0)			goto header;		icon->nplane = gets(&buf[4]);		icon->bits = gets(&buf[6]);		icon->len = getl(&buf[8]);		icon->offset = getl(&buf[12]);		if(i == 0)			h->first = icon;		else			h->last->next = icon;		h->last = icon;	}	return 0;eof:	werrstr("unexpected EOF");	return -1;header:	werrstr("unknown header format");	return -1;}uchar*transcmap(Icon *icon, uchar *map){	uchar *m, *p;	int i;	p = m = malloc(sizeof(int)*(1<<icon->bits));	for(i = 0; i < icon->ncolor; i++){		*p++ = rgb2cmap(map[2], map[1], map[0]);		map += 4;	}	return m;}Image*xor2img(Icon *icon, uchar *xor, uchar *map){	uchar *data;	Image *img;	int inxlen;	uchar *from, *to;	int s, byte, mask;	int x, y;	inxlen = 4*((icon->bits*icon->w+31)/32);	to = data = malloc(icon->w*icon->h);	/* rotate around the y axis, go to 8 bits, and convert color */	mask = (1<<icon->bits)-1;	for(y = 0; y < icon->h; y++){		s = -1;		byte = 0;		from = xor + (icon->h - 1 - y)*inxlen;		for(x = 0; x < icon->w; x++){			if(s < 0){				byte = *from++;				s = 8-icon->bits;			}			*to++ = map[(byte>>s) & mask];			s -= icon->bits;		}	}	/* stick in an image */	img = allocimage(display, Rect(0,0,icon->w,icon->h), CMAP8, 0, DNofill);	loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*icon->w);	free(data);	return img;}Image*and2img(Icon *icon, uchar *and){	uchar *data;	Image *img;	int inxlen;	int outxlen;	uchar *from, *to;	int x, y;	inxlen = 4*((icon->w+31)/32);	to = data = malloc(inxlen*icon->h);	/* rotate around the y axis and invert bits */	outxlen = (icon->w+7)/8;	for(y = 0; y < icon->h; y++){		from = and + (icon->h - 1 - y)*inxlen;		for(x = 0; x < outxlen; x++){			*to++ = ~(*from++);		}	}	/* stick in an image */	img = allocimage(display, Rect(0,0,icon->w,icon->h), GREY1, 0, DNofill);	loadimage(img, Rect(0,0,icon->w,icon->h), data, icon->h*outxlen);	free(data);	return img;}intBgeticon(Biobuf *b, Icon *icon){	ulong l;	ushort s;	uchar *xor;	uchar *and;	uchar *cm;	uchar *buf;	uchar *map2map;	Image *img;	Bseek(b, icon->offset, 0);	buf = malloc(icon->len);	if(buf == nil)		return -1;	if(Bread(b, buf, icon->len) != icon->len){		werrstr("unexpected EOF");		return -1;	}	/* this header's info takes precedence over previous one */	if(getl(buf) != 40){		werrstr("bad icon header");		return -1;	}	l = getl(buf+4);	if(l != icon->w)		icon->w = l;	l = getl(buf+8);	if(l>>1 != icon->h)		icon->h = l>>1;	s = gets(buf+12);	if(s != icon->nplane)		icon->nplane = s;	s = gets(buf+14);	if(s != icon->bits)		icon->bits = s;	/* limit what we handle */	switch(icon->bits){	case 1:	case 2:	case 4:	case 8:		break;	default:		werrstr("don't support %d bit pixels", icon->bits);		return -1;	}	if(icon->nplane != 1){		werrstr("don't support %d planes", icon->nplane);		return -1;	}	cm = buf + 40;	xor = cm + 4*icon->ncolor;	and = xor + icon->h*4*((icon->bits*icon->w+31)/32);	/* translate the color map to a plan 9 one */	map2map = transcmap(icon, cm);	/* convert the images */	icon->img = xor2img(icon, xor, map2map);	icon->mask = and2img(icon, and);	/* so that we save an image with a white background */	img = allocimage(display, icon->img->r, CMAP8, 0, DWhite);	draw(img, icon->img->r, icon->img, icon->mask, ZP);	icon->img = img;	free(buf);	free(map2map);	return 0;}voidusage(void){	fprint(2, "usage: %s [file]\n", argv0);	exits("usage");}enum{	Mimage,	Mmask,	Mexit,	Up= 1,	Down= 0,};char	*menu3str[] = {	[Mimage]	"write image",	[Mmask]		"write mask",	[Mexit]		"exit",	0,};Menu	menu3 = {	menu3str};Cursor sight = {	{-7, -7},	{0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,	 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,	 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,	 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,},	{0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,	 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,	 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,	 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,}};voidbuttons(int ud){	while((mouse.buttons==0) != ud)		mouse = emouse();}voidmesg(char *fmt, ...){	va_list arg;	char buf[1024];	static char obuf[1024];	va_start(arg, fmt);	vseprint(buf, buf+sizeof(buf), fmt, arg);	va_end(arg);	string(screen, screen->r.min, background, ZP, font, obuf);	string(screen, screen->r.min, display->white, ZP, font, buf);	strcpy(obuf, buf);}voiddoimage(Icon *icon){	int rv;	char file[256];	int fd;	rv = -1;	snprint(file, sizeof(file), "%dx%d.img", icon->w, icon->h);	fd = create(file, OWRITE, 0664);	if(fd >= 0){		rv = writeimage(fd, icon->img, 0);		close(fd);	}	if(rv < 0)		mesg("error writing %s: %r", file);	else		mesg("created %s", file);}voiddomask(Icon *icon){	int rv;	char file[64];	int fd;	rv = -1;	snprint(file, sizeof(file), "%dx%d.mask", icon->w, icon->h);	fd = create(file, OWRITE, 0664);	if(fd >= 0){		rv = writeimage(fd, icon->mask, 0);		close(fd);	}	if(rv < 0)		mesg("error writing %s: %r", file);	else		mesg("created %s", file);}voidapply(void (*f)(Icon*)){	Icon *icon;	esetcursor(&sight);	buttons(Down);	if(mouse.buttons == 4)		for(icon = h.first; icon; icon = icon->next)			if(ptinrect(mouse.xy, icon->sr)){				buttons(Up);				f(icon);				break;			}	buttons(Up);	esetcursor(0);}voidmenu(void){	int sel;	sel = emenuhit(3, &mouse, &menu3);	switch(sel){	case Mimage:		apply(doimage);		break;	case Mmask:		apply(domask);		break;	case Mexit:		exits(0);		break;	}}voidmousemoved(void){	Icon *icon;	for(icon = h.first; icon; icon = icon->next)		if(ptinrect(mouse.xy, icon->sr)){			mesg("%dx%d", icon->w, icon->h);			return;		}	mesg("");}enum{	BORDER= 1,};voideresized(int new){	Icon *icon;	Rectangle r;	if(new && getwindow(display, Refnone) < 0)		sysfatal("can't reattach to window");	draw(screen, screen->clipr, background, nil, ZP);	r.max.x = screen->r.min.x;	r.min.y = screen->r.min.y + font->height + 2*BORDER;	for(icon = h.first; icon != nil; icon = icon->next){		r.min.x = r.max.x + BORDER;		r.max.x = r.min.x + Dx(icon->img->r);		r.max.y = r.min.y + Dy(icon->img->r);		draw(screen, r, icon->img, nil, ZP);		border(screen, r, -BORDER, display->black, ZP);		icon->sr = r;	}	flushimage(display, 1);}voidmain(int argc, char **argv){	Biobuf in;	Icon *icon;	int fd;	Rectangle r;	Event e;	ARGBEGIN{	case 'd':		debug = 1;		break;	}ARGEND;	fd = -1;	switch(argc){	case 0:		fd = 0;		break;	case 1:		fd = open(argv[0], OREAD);		if(fd < 0)			sysfatal("opening: %r");		break;	default:		usage();		break;	}	Binit(&in, fd, OREAD);	if(Bgetheader(&in, &h) < 0)		sysfatal("reading header: %r");	initdraw(nil, nil, "ico");	background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, (128<<24)|(128<<16)|(128<<8)|0xFF);	einit(Emouse|Ekeyboard);	r.min = Pt(4, 4);	for(icon = h.first; icon != nil; icon = icon->next){		if(Bgeticon(&in, icon) < 0){			fprint(2, "bad rectangle: %r\n");			continue;		}		if(debug)			fprint(2, "w %ud h %ud ncolor %ud bits %ud len %lud offset %lud\n",			   icon->w, icon->h, icon->ncolor, icon->bits, icon->len, icon->offset);		r.max = addpt(r.min, Pt(icon->w, icon->h));		icon->r = r;		r.min.x += r.max.x;	}	eresized(0);	for(;;)		switch(event(&e)){		case Ekeyboard:			break;		case Emouse:			mouse = e.mouse;			if(mouse.buttons & 4)				menu();			else				mousemoved();			break;		}	/* not reached */}

⌨️ 快捷键说明

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