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

📄 font.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <bio.h>#include "proof.h"char	fname[NFONT][20];		/* font names */char lastload[NFONT][20];	/* last file name prefix loaded for this font */Font	*fonttab[NFONT][NSIZE];	/* pointers to fonts */int	fmap[NFONT];		/* what map to use with this font */static void	bufchar(Point, Subfont *, uchar *);static void	loadfont(int, int);static void	fontlookup(int, char *);static void	buildxheight(Biobuf*);static void	buildmap(Biobuf*);static void	buildtroff(char *);static void	addmap(int, char *, int);static char	*map(Rune*, int);static void	scanstr(char *, char *, char **);int	specfont;	/* somehow, number of special font */#define	NMAP	5#define	QUICK	2048	/* char values less than this are quick to look up */#define	eq(s,t)	strcmp((char *) s, (char *) t) == 0int	curmap	= -1;	/* what map are we working on */typedef struct Link Link;struct Link	/* link names together */{	uchar	*name;	int	val;	Link	*next;};typedef struct Map Map;struct Map	/* holds a mapping from uchar name to index */{	double	xheight;	Rune	quick[QUICK];	/* low values get special treatment */	Link	*slow;	/* other stuff goes into a link list */};Map	charmap[5];typedef struct Fontmap Fontmap;struct Fontmap	/* mapping from troff name to filename */{	char	*troffname;	char	*prefix;	int	map;		/* which charmap to use for this font */	char	*fallback;	/* font to look in if can't find char here */};Fontmap	fontmap[100];int	pos2fontmap[NFONT];	/* indexed by troff font position, gives Fontmap */int	nfontmap	= 0;	/* how many are there */voiddochar(Rune r[]){	char *s, *fb;	Font *f;	Point p;	int fontno, fm, i;	char buf[10];	fontno = curfont;	if((s = map(r, curfont)) == 0){		/* not on current font */		if ((s = map(r, specfont)) != 0)	/* on special font */			fontno = specfont;		else{			/* look for fallback */			fm = pos2fontmap[curfont];			fb = fontmap[fm].fallback;			if(fb){				/* see if fallback is mounted */				for(i = 0; i < NFONT; i++){					if(eq(fb, fontmap[pos2fontmap[i]].troffname)){						s = map(r, i);						if(s){							fontno = i;							goto found;						}					}				}			}			/* no such char; use name itself on defont */			/* this is not a general solution */			p.x = hpos/DIV + xyoffset.x + offset.x;			p.y = vpos/DIV + xyoffset.y + offset.y;			p.y -= font->ascent;			sprint(buf, "%S", r);			string(screen, p, display->black, ZP, font, buf);			return;		}	}    found:	p.x = hpos/DIV + xyoffset.x + offset.x;	p.y = vpos/DIV + xyoffset.y + offset.y;	while ((f = fonttab[fontno][cursize]) == 0)		loadfont(fontno, cursize);	p.y -= f->ascent;	dprint(2, "putting %S at %d,%d font %d, size %d\n", r, p.x, p.y, fontno, cursize);	string(screen, p, display->black, ZP, f, s);}static voidloadfont(int n, int s){	char file[100];	int i, fd, t, deep;	static char *try[3] = {"", "times/R.", "pelm/"};	Subfont *f;	Font *ff;	try[0] = fname[n];	for (t = 0; t < 3; t++){		i = s * mag * charmap[fmap[n]].xheight/0.72;	/* a pixel is 0.72 points */		if (i < MINSIZE)			i = MINSIZE;		dprint(2, "size %d, i %d, mag %g\n", s, i, mag);		for(; i >= MINSIZE; i--){			/* if .font file exists, take that */			sprint(file, "%s/%s%d.font", libfont, try[t], i);			ff = openfont(display, file);			if(ff != 0){				fonttab[n][s] = ff;				dprint(2, "using %s for font %d %d\n", file, n, s);				return;			}			/* else look for a subfont file */			for (deep = log2[screen->depth]; deep >= 0; deep--){				sprint(file, "%s/%s%d.%d", libfont, try[t], i, deep);				dprint(2, "trying %s for %d\n", file, i);				if ((fd = open(file, 0)) >= 0){					f = readsubfont(display, file, fd, 0);					if (f == 0) {						fprint(2, "can't rdsubfontfile %s: %r\n", file);						exits("rdsubfont");					}					close(fd);					ff = mkfont(f, 0);					if(ff == 0){						fprint(2, "can't mkfont %s: %r\n", file);						exits("rdsubfont");					}					fonttab[n][s] = ff;					dprint(2, "using %s for font %d %d\n", file, n, s);					return;				}			}		}	}	fprint(2, "can't find font %s.%d or substitute, quitting\n", fname[n], s);	exits("no font");}voidloadfontname(int n, char *s){	int i;	Font *f, *g = 0;	if (strcmp(s, fname[n]) == 0)		return;	if(fname[n] && fname[n][0]){		if(lastload[n] && strcmp(lastload[n], fname[n]) == 0)			return;		strcpy(lastload[n], fname[n]);	}	fontlookup(n, s);	for (i = 0; i < NSIZE; i++)		if (f = fonttab[n][i]){			if (f != g) {				freefont(f);				g = f;			}			fonttab[n][i] = 0;		}}voidallfree(void){	int i;	for (i=0; i<NFONT; i++)		loadfontname(i, "??");}voidreadmapfile(char *file){	Biobuf *fp;	char *p, cmd[100];	if ((fp=Bopen(file, OREAD)) == 0){		fprint(2, "proof: can't open map file %s\n", file);		exits("urk");	}	while((p=Brdline(fp, '\n')) != 0) {		p[Blinelen(fp)-1] = 0;		scanstr(p, cmd, 0);		if(p[0]=='\0' || eq(cmd, "#"))	/* skip comments, empty */			continue;		else if(eq(cmd, "xheight"))			buildxheight(fp);		else if(eq(cmd, "map"))			buildmap(fp);		else if(eq(cmd, "special"))			buildtroff(p);		else if(eq(cmd, "troff"))			buildtroff(p);		else			fprint(2, "weird map line %s\n", p);	}	Bterm(fp);}static voidbuildxheight(Biobuf *fp)	/* map goes from char name to value to print via *string() */{	char *line;	line = Brdline(fp, '\n');	if(line == 0){		fprint(2, "proof: bad map file\n");		exits("map");	}	charmap[curmap].xheight = atof(line);}static voidbuildmap(Biobuf *fp)	/* map goes from char name to value to print via *string() */{	uchar *p, *line, ch[100];	int val;	Rune r;	curmap++;	if(curmap >= NMAP){		fprint(2, "proof: out of char maps; recompile\n");		exits("charmap");	}	while ((line = Brdline(fp, '\n'))!= 0){		if (line[0] == '\n')			return;		line[Blinelen(fp)-1] = 0;		scanstr((char *) line, (char *) ch, (char **) &p);		if (ch[0] == '\0') {			fprint(2, "bad map file line '%s'\n", (char*)line);			continue;		}		val = strtol((char *) p, 0, 10);dprint(2, "buildmap %s (%x %x) %s %d\n", (char*)ch, ch[0], ch[1], (char*)p, val);		chartorune(&r, (char*)ch);		if(utflen((char*)ch)==1 && r<QUICK)			charmap[curmap].quick[r] = val;		else			addmap(curmap, strdup((char *) ch), val);	/* put somewhere else */	}}static voidaddmap(int n, char *s, int val)	/* stick a new link on */{	Link *p = (Link *) malloc(sizeof(Link));	Link *prev = charmap[n].slow;	if(p == 0)		exits("out of memory in addmap");	p->name = (uchar *) s;	p->val = val;	p->next = prev;	charmap[n].slow = p;}static voidbuildtroff(char *buf)	/* map troff names into bitmap filenames */{				/* e.g., R -> times/R., I -> times/I., etc. */	char *p, cmd[100], name[200], prefix[400], fallback[100];	scanstr(buf, cmd, &p);	scanstr(p, name, &p);	scanstr(p, prefix, &p);	while(*p!=0 && isspace(*p))		p++;	if(*p != 0){		scanstr(p, fallback, &p);		fontmap[nfontmap].fallback = strdup(fallback);	}else		fontmap[nfontmap].fallback = 0;	fontmap[nfontmap].troffname = strdup(name);	fontmap[nfontmap].prefix = strdup(prefix);	fontmap[nfontmap].map = curmap;	dprint(2, "troff name %s is bitmap %s map %d in slot %d fallback %s\n", name, prefix, curmap, nfontmap, fontmap[nfontmap].fallback? fontmap[nfontmap].fallback : "<null>");	nfontmap++;}static voidfontlookup(int n, char *s)	/* map troff name of s into position n */{	int i;	for(i = 0; i < nfontmap; i++)		if (eq(s, fontmap[i].troffname)) {			strcpy(fname[n], fontmap[i].prefix);			fmap[n] = fontmap[i].map;			pos2fontmap[n] = i;			if (eq(s, "S"))				specfont = n;			dprint(2, "font %d %s is %s\n", n, s, fname[n]);			return;		}	/* god help us if this font isn't there */}static char *map(Rune rp[], int font)	/* figure out mapping for char in this font */{	static char s[100];	char c[10];	Link *p;	Rune r;	if(rp[1]==0 &&  rp[0]<QUICK)	/* fast lookup */		r = charmap[fmap[font]].quick[rp[0]];	else {	/* high-valued or compound character name */		sprint(c, "%S", rp);		r = 0;		for (p = charmap[fmap[font]].slow; p; p = p->next)			if(eq(c, p->name)){				r = p->val;				break;			}	}	if(r == 0){	/* not there */		dprint(2, "didn't find %S font# %d\n", rp, font);		return 0;	}	dprint(2, "map %S to %s font# %d\n", rp, s, font);	s[runetochar(s, &r)] = 0;	return s;}static voidscanstr(char *s, char *ans, char **ep){	for (; isspace((uchar) *s); s++)		;	for (; *s!=0 && !isspace((uchar) *s); )		*ans++ = *s++;	*ans = 0;	if (ep)		*ep = s;}

⌨️ 快捷键说明

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