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

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

Ok, as promised and for what it's worth, here is a copy of my
limbo mkfont.b

usage: mkfont -biw fontpath pts

-b does fake embolden (by double-strike)
-i does fake italic (by shear)
-w does a bad job of enforcing fixed width for those fonts with poor metrics

It tends to create fonts that look to have too much leading.
This is because some subfonts have quite a lot of height - due to
diacritics etc.

Perhaps some options for constraining the unicode range might help.

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: 10224 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);
	# ensure glyph 0 exists
	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;

	# ensure that glyph 0 exists
	if (start == 0)
		first = 0;

	for (c := first; c <= end; c++) {
		if (c &&!face.haschar(c))
			continue;
		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(start, end, glyphs, 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 13:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-13 13:40 [9fans] Re: diacritics 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).