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

📄 font.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>static int	fontresize(Font*, int, int, int);static int	freeup(Font*);#define	PJW	0	/* use NUL==pjw for invisible characters */intcachechars(Font *f, char **ss, Rune **rr, ushort *cp, int max, int *wp, char **subfontname){	int i, th, sh, h, ld, w, rw, wid, nc;	char *sp;	Rune r, *rp, vr;	ulong a;	Cacheinfo *c, *tc, *ec;	if(ss){		sp = *ss;		rp = L"";	}else{		sp = "";		rp = *rr;	}	wid = 0;	*subfontname = 0;	for(i=0; i<max && (*sp || *rp); sp+=w, rp+=rw){		if(ss){			r = *(uchar*)sp;			if(r < Runeself)				w = 1;			else{				w = chartorune(&vr, sp);				r = vr;			}			rw = 0;		}else{			r = *rp;			w = 0;			rw = 1;		}		sh = (17 * (uint)r) & (f->ncache-NFLOOK-1);		c = &f->cache[sh];		ec = c+NFLOOK;		h = sh;		while(c < ec){			if(c->value==r && c->age)				goto Found;			c++;			h++;		}			/*		 * Not found; toss out oldest entry		 */		a = ~0;		th = sh;		tc = &f->cache[th];		while(tc < ec){			if(tc->age < a){				a = tc->age;				h = th;				c = tc;			}			tc++;			th++;		}		if(a && (f->age-a)<500){	/* kicking out too recent; resize */			nc = 2*(f->ncache-NFLOOK) + NFLOOK;			if(nc <= MAXFCACHE){				if(i == 0)					fontresize(f, f->width, nc, f->maxdepth);				/* else flush first; retry will resize */				break;			}		}		if(c->age == f->age)	/* flush pending string output */			break;		ld = loadchar(f, r, c, h, i, subfontname);		if(ld <= 0){			if(ld == 0)				continue;			break;		}		c = &f->cache[h];	/* may have reallocated f->cache */		    Found:		wid += c->width;		c->age = f->age;		cp[i] = h;		i++;	}	if(ss)		*ss = sp;	else		*rr = rp;	*wp = wid;	return i;}voidagefont(Font *f){	Cacheinfo *c, *ec;	Cachesubf *s, *es;	f->age++;	if(f->age == 65536){		/*		 * Renormalize ages		 */		c = f->cache;		ec = c+f->ncache;		while(c < ec){			if(c->age){				c->age >>= 2;				c->age++;			}			c++;		}		s = f->subf;		es = s+f->nsubf;		while(s < es){			if(s->age){				if(s->age<SUBFAGE && s->cf->name != nil){					/* clean up */					if(s->f != display->defaultsubfont)						freesubfont(s->f);					s->cf = nil;					s->f = nil;					s->age = 0;				}else{					s->age >>= 2;					s->age++;				}			}			s++;		}		f->age = (65536>>2) + 1;	}}static Subfont*cf2subfont(Cachefont *cf, Font *f){	int depth;	char *name;	Subfont *sf;	name = cf->subfontname;	if(name == nil){		if(f->display && f->display->screenimage)			depth = f->display->screenimage->depth;		else			depth = 8;		name = subfontname(cf->name, f->name, depth);		if(name == nil)			return nil;		cf->subfontname = name;	}	sf = lookupsubfont(f->display, name);	return sf;}/* return 1 if load succeeded, 0 if failed, -1 if must retry */intloadchar(Font *f, Rune r, Cacheinfo *c, int h, int noflush, char **subfontname){	int i, oi, wid, top, bottom;	Rune pic;	Fontchar *fi;	Cachefont *cf;	Cachesubf *subf, *of;	uchar *b;	pic = r;    Again:	for(i=0; i<f->nsub; i++){		cf = f->sub[i];		if(cf->min<=pic && pic<=cf->max)			goto Found;	}    TryPJW:	if(pic != PJW){		pic = PJW;		goto Again;	}	return 0;    Found:	/*	 * Choose exact or oldest	 */	oi = 0;	subf = &f->subf[0];	for(i=0; i<f->nsubf; i++){		if(cf == subf->cf)			goto Found2;		if(subf->age < f->subf[oi].age)			oi = i;		subf++;	}	subf = &f->subf[oi];	if(subf->f){		if(f->age-subf->age>SUBFAGE || f->nsubf>MAXSUBF){    Toss:			/* ancient data; toss */			freesubfont(subf->f);			subf->cf = nil;			subf->f = nil;			subf->age = 0;		}else{				/* too recent; grow instead */			of = f->subf;			f->subf = malloc((f->nsubf+DSUBF)*sizeof *subf);			if(f->subf == nil){				f->subf = of;				goto Toss;			}			memmove(f->subf, of, (f->nsubf+DSUBF)*sizeof *subf);			memset(f->subf+f->nsubf, 0, DSUBF*sizeof *subf);			subf = &f->subf[f->nsubf];			f->nsubf += DSUBF;			free(of);		}	}	subf->age = 0;	subf->cf = nil;	subf->f = cf2subfont(cf, f);	if(subf->f == nil){		if(cf->subfontname == nil)			goto TryPJW;		*subfontname = cf->subfontname;		return -1;	}	subf->cf = cf;	if(subf->f->ascent > f->ascent && f->display){		/* should print something? this is a mistake in the font file */		/* must prevent c->top from going negative when loading cache */		Image *b;		int d, t;		d = subf->f->ascent - f->ascent;		b = subf->f->bits;		draw(b, b->r, b, nil, addpt(b->r.min, Pt(0, d)));		draw(b, Rect(b->r.min.x, b->r.max.y-d, b->r.max.x, b->r.max.y), f->display->black, nil, b->r.min);		for(i=0; i<subf->f->n; i++){			t = subf->f->info[i].top-d;			if(t < 0)				t = 0;			subf->f->info[i].top = t;			t = subf->f->info[i].bottom-d;			if(t < 0)				t = 0;			subf->f->info[i].bottom = t;		}		subf->f->ascent = f->ascent;	}    Found2:	subf->age = f->age;	/* possible overflow here, but works out okay */	pic += cf->offset;	pic -= cf->min;	if(pic >= subf->f->n)		goto TryPJW;	fi = &subf->f->info[pic];	if(fi->width == 0)		goto TryPJW;	wid = (fi+1)->x - fi->x;	if(f->width < wid || f->width == 0 || f->maxdepth < subf->f->bits->depth){		/*		 * Flush, free, reload (easier than reformatting f->b)		 */		if(noflush)			return -1;		if(f->width < wid)			f->width = wid;		if(f->maxdepth < subf->f->bits->depth)			f->maxdepth = subf->f->bits->depth;		i = fontresize(f, f->width, f->ncache, f->maxdepth);		if(i <= 0)			return i;		/* c is still valid as didn't reallocate f->cache */	}	c->value = r;	top = fi->top + (f->ascent-subf->f->ascent);	bottom = fi->bottom + (f->ascent-subf->f->ascent);	c->width = fi->width;	c->x = h*f->width;	c->left = fi->left;	if(f->display == nil)		return 1;	flushimage(f->display, 0);	/* flush any pending errors */	b = bufimage(f->display, 37);	if(b == 0)		return 0;	b[0] = 'l';	BPLONG(b+1, f->cacheimage->id);	BPLONG(b+5, subf->f->bits->id);	BPSHORT(b+9, c-f->cache);	BPLONG(b+11, c->x);	BPLONG(b+15, top);	BPLONG(b+19, c->x+((fi+1)->x-fi->x));	BPLONG(b+23, bottom);	BPLONG(b+27, fi->x);	BPLONG(b+31, fi->top);	b[35] = fi->left;	b[36] = fi->width;	return 1;}/* release all subfonts, return number freed */staticintfreeup(Font *f){	Cachesubf *s, *es;	int nf;	if(f->sub[0]->name == nil)	/* font from mkfont; don't free */		return 0;	s = f->subf;	es = s+f->nsubf;	nf = 0;	while(s < es){		if(s->age){			freesubfont(s->f);			s->cf = nil;			s->f = nil;			s->age = 0;			nf++;		}		s++;	}	return nf;}/* return whether resize succeeded && f->cache is unchanged */static intfontresize(Font *f, int wid, int ncache, int depth){	Cacheinfo *i;	int ret;	Image *new;	uchar *b;	Display *d;	ret = 0;	if(depth <= 0)		depth = 1;	d = f->display;	if(d == nil)		goto Nodisplay;	new = allocimage(d, Rect(0, 0, ncache*wid, f->height), CHAN1(CGrey, depth), 0, 0);	if(new == nil){		fprint(2, "font cache resize failed: %r\n");		abort();		goto Return;	}	flushimage(d, 0);	/* flush any pending errors */	b = bufimage(d, 1+4+4+1);	if(b == 0){		freeimage(new);		goto Return;	}	b[0] = 'i';	BPLONG(b+1, new->id);	BPLONG(b+5, ncache);	b[9] = f->ascent;	if(flushimage(d, 0) < 0){		fprint(2, "resize: init failed: %r\n");		freeimage(new);		goto Return;	}	freeimage(f->cacheimage);	f->cacheimage = new;    Nodisplay:	f->width = wid;	f->maxdepth = depth;	ret = 1;	if(f->ncache != ncache){		i = malloc(ncache*sizeof f->cache[0]);		if(i != nil){			ret = 0;			free(f->cache);			f->ncache = ncache;			f->cache = i;		}		/* else just wipe the cache clean and things will be ok */	}    Return:	memset(f->cache, 0, f->ncache*sizeof f->cache[0]);	return ret;}

⌨️ 快捷键说明

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