9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] update to mkfont.b
@ 2003-08-13 15:10 chris
  0 siblings, 0 replies; only message in thread
From: chris @ 2003-08-13 15:10 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 291 bytes --]

Earlier version generated a lot of blank cell info.
This version trims each unicode block down to the range
of available glyphs.

e.g.
--rw-r--r-- M 9 chris chris 38803 Aug 13 14:16 comic.14.e000-f8ff
goes to
--rw-r--r-- M 9 chris chris 433 Aug 13 16:09 comic.14.f001-f005

Chris.

[-- Attachment #2.1: Type: text/plain, Size: 308 bytes --]

The following attachment had content that we can't
prove to be harmless.  To avoid possible automatic
execution, we changed the content headers.
The original header was:

	Content-Disposition: attachment; filename=mkfont.b
	Content-Type: text/plain; charset="US-ASCII"
	Content-Transfer-Encoding: 7bit

[-- Attachment #2.2: mkfont.b.suspect --]
[-- Type: application/octet-stream, Size: 10236 bytes --]

implement Mkfont;

include "sys.m";
include "draw.m";
include "arg.m";
include "freetype.m";

Mkfont: module {
	init: fn(ctxt: ref Draw->Context, args: list of string);
};


sys: Sys;
draw: Draw;
	Point, Rect, Image, Display: import draw;
ft: Freetype;
	Face, Glyph: import ft;

fixadv := 0;
dobold := 0;
dosheer := 0;

disp: ref Display;

Subfont: adt {
	start: int;
	end: int;
	glyphs: array of ref Freetype->Glyph;
	mintop: int;
	maxh: int;
	maxadv: int;
};

init(nil: ref Draw->Context, argv: list of string)
{
	sys = load Sys Sys->PATH;
	draw = checkload(load Draw Draw->PATH, Draw->PATH);
	arg := checkload(load Arg Arg->PATH, Arg->PATH);
	ft = checkload(load Freetype Freetype->PATH, Freetype->PATH);

	arg->init(argv);
	arg->setusage("mkfont [-biw] fontpath pts");
	while((opt := arg->opt()) != 0) {
		case opt{
		'b' =>
			dobold = 1;
		'i' =>
			dosheer = 1;
		'w' =>
			fixadv = 1;
		}
	}
	path := arg->earg();
	pts := int arg->earg();
	arg = nil;
	ftbase := sys->sprint("%s.%d", basename(path), pts);

	disp = Display.allocate(nil);
	face := ft->newface(path, 0);
	if (face == nil)
		error(sys->sprint("loading font %s: %r", path));

	if (dosheer) {
		m := ref Freetype->Matrix(1<<16, 1<<14, 0, 1<<16);
		face.settransform(m, nil);
	}
	err := face.setcharsize(pts<<6, 72, 72);
	if (err != nil)
		error(sys->sprint("cannot set point size: %s", err));

	mintop := 100000;
	maxh := 0;
	maxadv := 0;
	subfonts: list of ref Subfont;

	for (ix := 0; ix < len uniblk; ix += 2) {
		start := uniblk[ix];
		end := uniblk[ix+1];

		for (i := start; i <= end; i++) {
			if (face.haschar(i)) {
				sf := loadsubf(face, start, end, i);
				if (sf.mintop < mintop)
					mintop = sf.mintop;
				if (sf.maxh > maxh)
					maxh = sf.maxh;
				if (sf.maxadv > maxadv)
					maxadv = sf.maxadv;
				subfonts = sf :: subfonts;
				break;
			}
		}
	}
	subfonts = rev(subfonts);
	if (subfonts == nil || (hd subfonts).start != 0)
		subfonts = loadsubf(face, 0, 0, 0) :: subfonts;

	if (mintop < 0)
		mintop = 0;
	ascent := face.ascent - mintop;
	height := maxh-mintop;

	ftpath := ftbase+".font";
	ftfd := sys->create(ftpath, Sys->OWRITE, 8r666);
	if (ftfd == nil)
		error(sys->sprint("failed to create %s: %r", ftpath));

	sys->fprint(ftfd, "%d %d\n", height, ascent);
	for (; subfonts != nil; subfonts = tl subfonts) {
		sf := hd subfonts;
		sfpath := sys->sprint("%s.%.4x-%.4x", ftbase, sf.start, sf.end);
		sffd := sys->create(sfpath, Sys->OWRITE, 8r666);
		if (sffd == nil) {
			sys->fprint(stderr(), "cannot create %s: %r\n", sfpath);
			continue;
		}

		glyphs := sf.glyphs;
		h := sf.maxh-sf.mintop;
		w := 0;
		for (ix = 0; ix < len glyphs; ix++) {
			g := glyphs[ix];
			if (g != nil) {
				w += g.width;
				if (sf.mintop > 0)
					g.top -= sf.mintop;
				if (fixadv)
					g.advance.x = maxadv;
				if (dobold) {
					g.advance.x += 1<<6;	# glyph advance is 26.6 fixed point
					w++;
				}
			}
		}
		if (writesubf(sffd, glyphs, ascent, w, h))
			sys->fprint(ftfd, "0x%.4x\t0x%.4x\t%s\n", sf.start, sf.end, sfpath);
	}
}

loadsubf(face: ref Freetype->Face, start: int, end: int, first: int): ref Subfont
{
	mintop := 100000;
	maxh := 0;
	maxadv := 0;
	glyphs := array [end-start+1] of ref Freetype->Glyph;

	# force glyph 0
	if (start == 0)
		first = 0;
	last := 0;
	for (c := first; c <= end; c++) {
		if (c &&!face.haschar(c))
			continue;
		last = c;
		g := face.loadglyph(c);
		if (g == nil)
			continue;
		glyphs[c-start] = g;
		g.top = face.ascent - g.top;
		if (g.top < mintop)
			mintop = g.top;
		h := g.top + g.height;
		if (h > maxh)
			maxh = h;
		if (g.advance.x > maxadv);
			maxadv = g.advance.x;
	}
	return ref Subfont(first, last, glyphs[first-start:last-start+1], mintop, maxh, maxadv);
}

writesubf(fd: ref Sys->FD, glyphs: array of ref Glyph, ascent, width, height: int): int
{
	ir := Rect((0, 0), (width, height));
	img := disp.newimage(ir, Draw->GREY8, 0, Draw->Black);
	if (img == nil) {
		sys->fprint(stderr(), "cannot create subfont image: %r\n");
		return 0;
	}

	nextx := 0;
	for (c := 0; c < len glyphs; c++) {
		g := glyphs[c];
		if (g == nil)
			continue;
		dstr := Rect((nextx, g.top), (nextx+g.width, g.top+g.height));
		img.writepixels(dstr, g.bitmap);
		nextx += g.width;
		if (dobold)
			nextx++;
	}
	if (dobold)
		img.drawop(Rect((1,0), (ir.max.x, ir.max.y)), disp.white, img, Point(0,0), Draw->SoverD);

	disp.writeimage(fd, img);
	writeglyphinfo(fd, glyphs, height, ascent);
	return 1;
}

writeglyphinfo(fd: ref Sys->FD, glyphs: array of ref Glyph, height, ascent: int)
{
	sys->fprint(fd, "%11d %11d %11d ", len glyphs, height, ascent);
	empty := ref Freetype->Glyph (0, 0, 0, 0, (0, 0), nil);
	nextx := 0;
	for (ix := 0; ix < len glyphs; ix++) {
		g := glyphs[ix];
		if (g == nil)
			g = empty;
		writeglyph(fd, g, nextx);
		nextx += g.width;
		if (g != empty && dobold)
			nextx++;
	}
	writeglyph(fd, empty, nextx);
}

writeglyph(fd: ref Sys->FD, g: ref Freetype->Glyph, x: int)
{
	b := array [6] of byte;
	ix := 0;

	b[ix++] = byte (x & 16rff);			# x low order
	b[ix++] = byte ((x>>8) & 16rff);		# x high order
	b[ix++] = byte (g.top & 16rff);		# top
	b[ix++] = byte ((g.top + g.height) & 16rff);	# bottom
	b[ix++] = byte (g.left & 16rff);		# left
	b[ix++] = byte ((g.advance.x >> 6)& 16rff);

	sys->write(fd, b, ix);
}

checkload[T](x: T, p: string): T
{
	if(x == nil)
		error(sys->sprint("cannot load %s: %r\n", p));
	return x;
}

rev[T](l: list of T): list of T
{
	n: list of T;
	for (; l != nil; l = tl l)
		n = hd l :: n;
	return n;
}

stderr(): ref Sys->FD
{
	return sys->fildes(2);
}

error(e: string)
{
	sys->fprint(stderr(), "remotelogon: %s\n", e);
	raise "fail:error";
}

basename(s: string): string
{
	for ((nil, ls) := sys->tokenize(s, "/"); ls != nil; ls = tl ls)
		s = hd ls;
	for (i := len s - 1; i >= 0; i--) {
		if (s[i] == '.')
			break;
	}
	if (i < 0)
		return s;
	return s[:i];
}

uniblk := array [] of {
	16r0000, 16r007F,	# Basic Latin
	16r0080, 16r00FF,	# Latin-1 Supplement
	16r0100, 16r017F,	# Latin Extended-A
	16r0180, 16r024F,	# Latin Extended-B
	16r0250, 16r02AF,	# IPA Extensions
	16r02B0, 16r02FF,	# Spacing Modifier Letters
	16r0300, 16r036F,	# Combining Diacritical Marks
	16r0370, 16r03FF,	# Greek and Coptic
	16r0400, 16r04FF,	# Cyrillic
	16r0500, 16r052F,	# Cyrillic Supplementary
	16r0530, 16r058F,	# Armenian
	16r0590, 16r05FF,	# Hebrew
	16r0600, 16r06FF,	# Arabic
	16r0700, 16r074F,	# Syriac
	16r0780, 16r07BF,	# Thaana
	16r0900, 16r097F,	# Devanagari
	16r0980, 16r09FF,	# Bengali
	16r0A00, 16r0A7F,	# Gurmukhi
	16r0A80, 16r0AFF,	# Gujarati
	16r0B00, 16r0B7F,	# Oriya
	16r0B80, 16r0BFF,	# Tamil
	16r0C00, 16r0C7F,	# Telugu
	16r0C80, 16r0CFF,	# Kannada
	16r0D00, 16r0D7F,	# Malayalam
	16r0D80, 16r0DFF,	# Sinhala
	16r0E00, 16r0E7F,	# Thai
	16r0E80, 16r0EFF,	# Lao
	16r0F00, 16r0FFF,	# Tibetan
	16r1000, 16r109F,	# Myanmar
	16r10A0, 16r10FF,	# Georgian
	16r1100, 16r11FF,	# Hangul Jamo
	16r1200, 16r137F,	# Ethiopic
	16r13A0, 16r13FF,	# Cherokee
	16r1400, 16r167F,	# Unified Canadian Aboriginal Syllabics
	16r1680, 16r169F,	# Ogham
	16r16A0, 16r16FF,	# Runic
	16r1700, 16r171F,	# Tagalog
	16r1720, 16r173F,	# Hanunoo
	16r1740, 16r175F,	# Buhid
	16r1760, 16r177F,	# Tagbanwa
	16r1780, 16r17FF,	# Khmer
	16r1800, 16r18AF,	# Mongolian
	16r1900, 16r194F,	# Limbu
	16r1950, 16r197F,	# Tai Le
	16r19E0, 16r19FF,	# Khmer Symbols
	16r1D00, 16r1D7F,	# Phonetic Extensions
	16r1E00, 16r1EFF,	# Latin Extended Additional
	16r1F00, 16r1FFF,	# Greek Extended
	16r2000, 16r206F,	# General Punctuation
	16r2070, 16r209F,	# Superscripts and Subscripts
	16r20A0, 16r20CF,	# Currency Symbols
	16r20D0, 16r20FF,	# Combining Diacritical Marks for Symbols
	16r2100, 16r214F,	# Letterlike Symbols
	16r2150, 16r218F,	# Number Forms
	16r2190, 16r21FF,	# Arrows
	16r2200, 16r22FF,	# Mathematical Operators
	16r2300, 16r23FF,	# Miscellaneous Technical
	16r2400, 16r243F,	# Control Pictures
	16r2440, 16r245F,	# Optical Character Recognition
	16r2460, 16r24FF,	# Enclosed Alphanumerics
	16r2500, 16r257F,	# Box Drawing
	16r2580, 16r259F,	# Block Elements
	16r25A0, 16r25FF,	# Geometric Shapes
	16r2600, 16r26FF,	# Miscellaneous Symbols
	16r2700, 16r27BF,	# Dingbats
	16r27C0, 16r27EF,	# Miscellaneous Mathematical Symbols-A
	16r27F0, 16r27FF,	# Supplemental Arrows-A
	16r2800, 16r28FF,	# Braille Patterns
	16r2900, 16r297F,	# Supplemental Arrows-B
	16r2980, 16r29FF,	# Miscellaneous Mathematical Symbols-B
	16r2A00, 16r2AFF,	# Supplemental Mathematical Operators
	16r2B00, 16r2BFF,	# Miscellaneous Symbols and Arrows
	16r2E80, 16r2EFF,	# CJK Radicals Supplement
	16r2F00, 16r2FDF,	# Kangxi Radicals
	16r2FF0, 16r2FFF,	# Ideographic Description Characters
	16r3000, 16r303F,	# CJK Symbols and Punctuation
	16r3040, 16r309F,	# Hiragana
	16r30A0, 16r30FF,	# Katakana
	16r3100, 16r312F,	# Bopomofo
	16r3130, 16r318F,	# Hangul Compatibility Jamo
	16r3190, 16r319F,	# Kanbun
	16r31A0, 16r31BF,	# Bopomofo Extended
	16r31F0, 16r31FF,	# Katakana Phonetic Extensions
	16r3200, 16r32FF,	# Enclosed CJK Letters and Months
	16r3300, 16r33FF,	# CJK Compatibility
	16r3400, 16r4DBF,	# CJK Unified Ideographs Extension A
	16r4DC0, 16r4DFF,	# Yijing Hexagram Symbols
	16r4E00, 16r9FFF,	# CJK Unified Ideographs
	16rA000, 16rA48F,	# Yi Syllables
	16rA490, 16rA4CF,	# Yi Radicals
	16rAC00, 16rD7AF,	# Hangul Syllables
	16rD800, 16rDB7F,	# High Surrogates
	16rDB80, 16rDBFF,	# High Private Use Surrogates
	16rDC00, 16rDFFF,	# Low Surrogates
	16rE000, 16rF8FF,	# Private Use Area
	16rF900, 16rFAFF,	# CJK Compatibility Ideographs
	16rFB00, 16rFB4F,	# Alphabetic Presentation Forms
	16rFB50, 16rFDFF,	# Arabic Presentation Forms-A
	16rFE00, 16rFE0F,	# Variation Selectors
	16rFE20, 16rFE2F,	# Combining Half Marks
	16rFE30, 16rFE4F,	# CJK Compatibility Forms
	16rFE50, 16rFE6F,	# Small Form Variants
	16rFE70, 16rFEFF,	# Arabic Presentation Forms-B
	16rFF00, 16rFFEF,	# Halfwidth and Fullwidth Forms
	16rFFF0, 16rFFFF,	# Specials
};

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-08-13 15:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-13 15:10 [9fans] update to mkfont.b chris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).