Charles.Forsyth20060303a828770d19 years agoHistory
179 lines · 4.6 KB · Brainfuck
RawDownload
implement CSSfont;include "sys.m";	sys: Sys;include "draw.m";	draw: Draw;	Font: import draw;include "units.m";	units: Units;include "cssfont.m"; # locally available font stylesBOLD, CW, ITALIC, PLAIN, NSTYLES: con iota;NSIZES: con 5;			# number of locally available font sizes fonts := array[] of {	PLAIN => array[] of {		"/fonts/charon/plain.tiny.font",		"/fonts/charon/plain.small.font",		"/fonts/charon/plain.normal.font",		"/fonts/charon/plain.large.font",		"/fonts/charon/plain.vlarge.font",	},	BOLD => array[] of {		"/fonts/charon/bold.tiny.font",		"/fonts/charon/bold.small.font",		"/fonts/charon/bold.normal.font",		"/fonts/charon/bold.large.font",		"/fonts/charon/bold.vlarge.font",		},	CW => array[] of {		"/fonts/charon/cw.tiny.font",		"/fonts/charon/cw.small.font",		"/fonts/charon/cw.normal.font",		"/fonts/charon/cw.large.font",		"/fonts/charon/cw.vlarge.font",		},	ITALIC => array[] of {		"/fonts/charon/italic.tiny.font",		"/fonts/charon/italic.small.font",		"/fonts/charon/italic.normal.font",		"/fonts/charon/italic.large.font",		"/fonts/charon/italic.vlarge.font",	},}; fontinfo := array[NSTYLES] of array of ref Font;sizechoice := array[NSTYLES] of array of byte; init(displ: ref Draw->Display){	sys = load Sys Sys->PATH;	draw = load Draw Draw->PATH;	units = load Units Units->PATH;	if (units == nil) {		sys->fprint(sys->fildes(2), "cssfont: cannot load %s: %r\n", Units->PATH);		raise "fail:bad module";	}	units->init(); 	for (i := 0; i < len fonts; i++) {		fpaths := fonts[i];		fontinfo[i] = array[len fpaths] of ref Font; 		# could make this process lazier, only computing sizes		# when a font of a particular class was asked for.		maxheight := 0;		for (j := 0; j < len fpaths; j++) {			if ((fontinfo[i][j] = f := Font.open(displ, fpaths[j])) == nil) {				sys->fprint(sys->fildes(2), "cssfont: font %s unavailable: %r\n", fpaths[j]);				raise "fail:font unavailable";			}			if (f.height > maxheight)				maxheight = f.height;		}		sizechoice[i] = array[maxheight + 1] of byte;		for (j = 0; j < maxheight + 1; j++)			sizechoice[i][j] = byte matchheight(j, fontinfo[i]);	} #	for (i = 0; i < NSTYLES; i++) {#		sys->print("class %d\n", i);#		for (j := 0; j < NSIZES; j++) {#			sys->print("	height %d; translates to %d [%d]\n",#				fontinfo[i][j].height,#				int sizechoice[i][fontinfo[i][j].height],#				fontinfo[i][int sizechoice[i][fontinfo[i][j].height]].height);#		}#	}} # find the closest match to a given desired height from the choices given.matchheight(desired: int, choices: array of ref Font): int{	n := len choices;	if (desired <= choices[0].height)		return 0;	if (desired >= choices[n - 1].height)		return n - 1;	for (i := 1; i < n; i++) {		if (desired >= choices[i - 1].height &&				desired <= choices[i].height) {			if (desired - choices[i - 1].height <					choices[i].height - desired)				return i - 1;			else				return i;		}	}	sys->fprint(sys->fildes(2), "cssfont: can't happen!\n");	raise "error";	return -1;		# should never happen} # get an appropriate font given the css specification.getfont(spec: Spec, parentem, parentex: int): (string, int, int){#sys->print("getfont size:%s family:%s; style:%s; weight:%s -> ",#		spec.size, spec.family, spec.style, spec.weight);	class := getclass(spec);	i := choosesize(class, spec.size, parentem, parentex); #sys->print("%s (height:%d)\n", fonts[class][i], fontinfo[class][i].height); 	# XXX i suppose we should really find out what height(widgth?) the 'x' is.	return (fonts[class][i], fontinfo[class][i].height, fontinfo[class][i].height);} getclass(spec: Spec): int{	if (spec.family == "monospace")		return CW;	if (spec.style == "italic")		return ITALIC;	if (spec.weight == "bold")		return BOLD;	return PLAIN;} choosesize(class: int, size: string, parentem, parentex: int): int{	if (size != nil && (size[0] >= '0' && size[0] <= '9')) {		(height, nil) := units->length(size, parentem, parentex, nil);		choices := sizechoice[class];		if (height > len choices)			height = len choices - 1;		return int choices[height];	}	case size {	"xx-small" or	"x-small" =>		return 0;	"small" =>		return 1;	"medium" =>		return 2;	"large" =>		return 3;	"x-large" or	"xx-large" =>		return 4;	"larger" or	"smaller" =>		choice := sizechoice[class];		if (parentem >= len choice)			parentem = len choice - 1;		i := int choice[parentem];		if (size[0] == 's') {			if (i > 0)				i--;		} else {			if (i < len fonts[class] - 1)				i++;		}		return i;	* =>		sys->fprint(sys->fildes(2), "cssfont: unknown font size spec '%s'\n", size);		return 2;	}}