juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

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))