mkcalcfont.py (4197B)
1 #!/usr/bin/env python3 2 """Genera calc/gfx/calcfont.c: fuentes de la calculadora desde las X11 misc-fixed 3 ISO10646 (dominio publico). Latin-1 32..255 y, en los huecos 0x80..0x9F, simbolos 4 matematicos (ver CUSTOM; la misma tabla esta en gfx/calc_gfx.h como CF_*). 5 Uso: python3 tools/mkcalcfont.py > gfx/calcfont.c""" 6 import gzip 7 from PIL import PcfFontFile as P 8 9 FONTS = [("cf_big", "8x13", 8, 13), ("cf_bold", "8x13B", 8, 13), ("cf_small", "6x12", 6, 12)] 10 11 # codigo propio -> (codepoint unicode, o (base, acento) para sintetizar) 12 CUSTOM = { 13 0x80: 0x03C0, 0x81: 0x221A, 0x82: 0x207B, 0x83: 0x2264, 0x84: 0x2265, 0x85: 0x2260, 14 0x86: 0x2192, 0x87: 0x2220, 0x88: ("x", "hat"), 0x89: ("y", "hat"), 0x8A: ("x", "bar"), 15 0x8B: ("y", "bar"), 0x8C: 0x25A1, 0x8D: 0x03A3, 0x8E: 0x03C3, 0x8F: 0x03B8, 0x90: 0x221E, 16 0x91: 0x21D4, 0x92: 0x25B6, 0x93: 0x25BC, 0x94: 0x25B2, 0x95: 0x25C0, 0x96: 0x1D07, 17 0x97: 0x2190, 0x98: 0x2191, 0x99: 0x2193, 0x9A: 0x221B, 0x9B: 0x2248, 0x9C: 0x03A0, 0x9D: 0x222B, 0x9E: 0x2032, 0x9F: 0x2033, 18 } 19 20 21 def load(name): 22 f = P.PcfFontFile(gzip.open("/usr/share/fonts/misc/%s.pcf.gz" % name, "rb"), "iso8859-1") 23 metrics = f._load_metrics() 24 bitmaps = f._load_bitmaps(metrics) 25 fp, fmt, i16, i32 = f._getformat(P.PCF_BDF_ENCODINGS) 26 fc, lc = i16(fp.read(2)), i16(fp.read(2)) 27 fr, lr = i16(fp.read(2)), i16(fp.read(2)) 28 i16(fp.read(2)) 29 ncols = lc - fc + 1 30 offs = [i16(fp.read(2)) for _ in range(ncols * (lr - fr + 1))] 31 props = f.info 32 33 def glyph(cp): 34 row, col = cp >> 8, cp & 255 35 if not (fr <= row <= lr and fc <= col <= lc): 36 return None 37 ix = offs[(row - fr) * ncols + (col - fc)] 38 if ix == 0xFFFF: 39 return None 40 return metrics[ix], bitmaps[ix] 41 asc = int(props.get(b"FONT_ASCENT", b"0") or 0) if isinstance(props, dict) else 0 42 return glyph, asc 43 44 45 def bits_of(glyph, cp, w, h, asc): 46 g = glyph(cp) 47 bits = [0] * h 48 if not g: 49 return None 50 (xsize, ysize, left, right, width, gasc, gdesc, attr), im = g 51 px = im.load() 52 top = asc - gasc 53 for yy in range(im.size[1]): 54 for xx in range(im.size[0]): 55 if px[xx, yy]: 56 r, c = top + yy, left + xx 57 if 0 <= r < h and 0 <= c < 8: 58 bits[r] |= 0x80 >> c 59 return bits 60 61 62 print("/* calcfont.c - GENERADO por tools/mkcalcfont.py desde las fuentes X11 misc-fixed") 63 print(" * ISO10646 (dominio publico). 32..255; 0x80..0x9F son simbolos (CF_* en calc_gfx.h). */") 64 print('#include "calc_gfx.h"\n') 65 for cname, fname, w, h in FONTS: 66 glyph, asc = load(fname) 67 if not asc: 68 asc = h - 2 69 rows = [] 70 for ch in range(32, 256): 71 c = CUSTOM.get(ch) 72 if c is None: 73 b = bits_of(glyph, ch, w, h, asc) if not (0x80 <= ch < 0xA0) else None 74 elif isinstance(c, tuple): 75 base, acc = c 76 b = bits_of(glyph, ord(base), w, h, asc) or [0] * h 77 # primera fila con tinta de la letra (x minuscula: altura x) 78 top = next((i for i, v in enumerate(b) if v), h // 2) 79 mask = 0 80 for v in b: 81 mask |= v 82 lo = next(i for i in range(8) if mask & (0x80 >> i)) if mask else 1 83 hi = max(i for i in range(8) if mask & (0x80 >> i)) if mask else w - 2 84 if acc == "bar": 85 row = max(0, top - 2) 86 for i in range(lo, hi + 1): 87 b[row] |= 0x80 >> i 88 else: 89 mid = (lo + hi) // 2 90 r1, r0 = max(0, top - 3), max(0, top - 2) 91 b[r1] |= 0x80 >> mid 92 b[r0] |= (0x80 >> max(lo, mid - 1)) | (0x80 >> min(hi, mid + 1)) 93 else: 94 b = bits_of(glyph, c, w, h, asc) 95 if b is None and c == 0x1D07: 96 b = bits_of(glyph, ord("E"), w, h, asc) 97 rows.append(b or [0] * h) 98 print("static const uint8_t %s_bits[224][%d] = {" % (cname, h)) 99 for i, bits in enumerate(rows): 100 print(" {" + ",".join("0x%02x" % v for v in bits) + "}, /* %d */" % (i + 32)) 101 print("};") 102 print("const Font %s = { %d, %d, &%s_bits[0][0] };\n" % (cname, w, h, cname))