Created
May 13, 2024 21:27
-
-
Save placek/1bb83e079c5089cb308e31d9509f4cf7 to your computer and use it in GitHub Desktop.
MiniGent TTF font generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env nix-shell | |
#! nix-shell -i python3 -p "(pkgs.python3.withPackages (python-pkgs: [ python-pkgs.fontforge python-pkgs.shapely ]))" | |
import fontforge | |
import os | |
import tempfile | |
from shapely import MultiPolygon, Polygon, box, unary_union | |
from shapely.affinity import translate | |
glyph_data = { | |
'!': [0,1,0,0,1,0,0,0,0,0,1,0], | |
'$': [0,1,0,1,1,1,0,1,1,1,1,1,0,1,0], | |
'%': [0,0,1,1,1,0,0,1,0,1,0,1], | |
'&': [0,1,1,0,1,1,1,0,1,0,1,1], | |
'(': [0,0,1,0,1,0,0,1,0,0,0,1], | |
')': [1,0,0,0,1,0,0,1,0,1,0,0], | |
'+': [0,0,0,0,1,0,1,1,1,0,1,0], | |
',': [0,0,0,0,0,0,0,0,0,0,1,0,0,1,0], | |
'-': [0,0,0,0,0,0,1,1,0,0,0,0], | |
'—': [0,0,0,0,0,0,1,1,1,0,0,0], | |
'.': [0,0,0,0,0,0,0,0,0,0,1,0], | |
'<': [0,0,0,0,1,0,1,0,0,0,1,0], | |
'>': [0,0,0,0,1,0,0,0,1,0,1,0], | |
'/': [0,0,1,0,1,0,0,1,0,1,0,0], | |
'0': [1,1,1,1,0,1,1,0,1,1,1,1], | |
'1': [0,1,0,1,1,0,0,1,0,1,1,1], | |
'2': [1,1,0,0,0,1,1,1,0,1,1,1], | |
'3': [1,1,1,0,0,1,0,1,1,1,1,1], | |
'4': [1,0,0,1,0,1,1,1,1,0,0,1], | |
'5': [1,1,1,1,1,0,0,0,1,1,1,0], | |
'6': [0,1,1,1,0,0,1,1,1,1,1,1], | |
'7': [1,1,1,0,0,1,0,1,0,0,1,0], | |
'8': [1,1,1,1,1,1,1,0,1,1,1,1], | |
'9': [1,1,1,1,1,1,0,0,1,1,1,0], | |
':': [0,0,0,0,1,0,0,0,0,0,1,0], | |
';': [0,0,0,0,1,0,0,0,0,0,1,0,0,1,0], | |
'=': [0,0,0,1,1,1,0,0,0,1,1,1], | |
'?': [1,1,0,0,0,1,0,0,0,0,1,0], | |
'@': [0,1,1,1,1,0,1,1,1,0,0,0,0,1,1,0], | |
'A': [0,1,0,1,0,1,1,1,1,1,0,1], | |
'B': [1,1,0,1,1,0,1,0,1,1,1,0], | |
'C': [0,1,1,1,0,0,1,0,0,0,1,1], | |
'D': [1,1,0,1,0,1,1,0,1,1,1,0], | |
'E': [0,1,1,1,0,0,1,1,0,1,1,1], | |
'F': [0,1,1,1,0,0,1,1,0,1,0,0], | |
'G': [0,1,1,1,0,0,1,0,1,0,1,1], | |
'H': [1,0,1,1,0,1,1,1,1,1,0,1], | |
'I': [1,1,1,0,1,0,0,1,0,1,1,1], | |
'J': [0,1,1,0,0,1,0,0,1,1,1,0], | |
'K': [1,0,1,1,0,1,1,1,0,1,0,1], | |
'L': [1,0,0,1,0,0,1,0,0,0,1,1], | |
'M': [1,1,1,1,1,1,1,0,1,1,0,1], | |
'N': [1,1,0,1,0,1,1,0,1,1,0,1], | |
'O': [0,1,0,1,0,1,1,0,1,0,1,0], | |
'P': [1,1,0,1,0,1,1,1,0,1,0,0], | |
'Q': [0,1,0,1,0,1,1,0,1,0,1,1], | |
'R': [1,1,0,1,0,1,1,1,0,1,0,1], | |
'S': [0,1,1,1,0,0,0,1,1,1,1,0], | |
'T': [1,1,1,0,1,0,0,1,0,0,1,0], | |
'U': [1,0,1,1,0,1,1,0,1,0,1,1], | |
'V': [1,0,1,1,0,1,1,0,1,0,1,0], | |
'W': [1,0,1,1,0,1,1,1,1,1,1,1], | |
'X': [1,0,1,1,0,1,0,1,0,1,0,1], | |
'Y': [1,0,1,1,0,1,0,1,0,0,1,0], | |
'Z': [1,1,1,0,0,1,0,1,0,1,1,1], | |
'[': [0,1,1,0,1,0,0,1,0,0,1,1], | |
'\"': [0,1,1,0,1,1,0,0,0,0,0,0], | |
'\'': [0,1,0,0,1,0,0,0,0,0,0,0], | |
'\\': [1,0,0,0,1,0,0,1,0,0,0,1], | |
']': [1,1,0,0,1,0,0,1,0,1,1,0], | |
'^': [0,1,0,1,0,1,0,0,0,0,0,0], | |
'_': [0,0,0,0,0,0,0,0,0,1,1,1], | |
'`': [0,1,0,0,0,1,0,0,0,0,0,0], | |
'a': [0,0,0,0,1,1,1,0,1,1,1,1], | |
'b': [1,0,0,1,1,1,1,0,1,1,1,1], | |
'c': [0,0,0,1,1,1,1,0,0,1,1,1], | |
'd': [0,0,1,1,1,1,1,0,1,1,1,1], | |
'e': [0,0,0,1,1,1,1,0,1,1,1,0], | |
'f': [0,1,0,1,0,0,1,1,0,1,0,0], | |
'g': [0,0,0,1,1,1,1,1,1,0,0,1,1,1,1], | |
'h': [1,0,0,1,1,1,1,0,1,1,0,1], | |
'i': [0,1,0,0,0,0,0,1,0,0,1,0], | |
'j': [0,1,0,0,0,0,0,1,0,0,1,0,1,1,0], | |
'k': [1,0,0,1,0,1,1,1,0,1,0,1], | |
'l': [0,1,0,0,1,0,0,1,0,0,0,1], | |
'm': [0,0,0,1,1,1,1,1,1,1,0,1], | |
'n': [0,0,0,1,1,1,1,0,1,1,0,1], | |
'o': [0,0,0,1,1,1,1,0,1,1,1,1], | |
'p': [0,0,0,1,1,1,1,0,1,1,1,1,1,0,0], | |
'q': [0,0,0,1,1,1,1,0,1,1,1,1,0,0,1], | |
'r': [0,0,0,1,1,0,1,0,0,1,0,0], | |
's': [0,0,0,0,1,1,0,1,0,1,1,0], | |
't': [0,1,0,1,1,1,0,1,0,0,1,0], | |
'u': [0,0,0,1,0,1,1,0,1,1,1,1], | |
'v': [0,0,0,1,0,1,1,0,1,0,1,0], | |
'w': [0,0,0,1,0,1,1,1,1,1,1,1], | |
'x': [0,0,0,1,0,1,0,1,0,1,0,1], | |
'y': [0,0,0,1,0,1,1,1,1,0,0,1,1,1,1], | |
'z': [0,0,0,1,1,0,0,1,0,0,1,1], | |
'{': [0,1,1,0,1,0,1,1,0,0,1,1], | |
'|': [0,1,0,0,1,0,0,1,0,0,1,0], | |
'}': [1,1,0,0,1,0,0,1,1,1,1,0], | |
'~': [0,0,0,0,0,1,0,1,1,0,1,0,0,0,0,0], | |
'Α': [0,1,0,1,0,1,1,1,1,1,0,1], | |
'Β': [1,1,0,1,1,1,1,0,1,1,1,1], | |
'Γ': [1,1,1,1,0,0,1,0,0,1,0,0], | |
'Δ': [0,1,0,1,0,1,1,0,1,1,1,1], | |
'Ε': [1,1,1,1,0,0,1,1,0,1,1,1], | |
'Ζ': [1,1,1,0,0,1,0,1,0,1,1,1], | |
'Η': [1,0,1,1,1,1,1,0,1,1,0,1], | |
'Θ': [0,1,1,1,0,1,1,1,1,1,1,1], | |
'Ι': [0,1,0,0,1,0,0,1,0,0,1,0], | |
'Κ': [1,0,1,1,1,0,1,0,1,1,0,1], | |
'Λ': [0,1,0,1,0,1,1,0,1,1,0,1], | |
'Μ': [1,1,0,1,1,1,1,0,1,1,0,1], | |
'Ν': [0,1,1,1,0,1,1,0,1,1,0,1], | |
'Ξ': [1,1,1,0,0,0,0,1,0,1,1,1], | |
'Ο': [0,1,1,1,0,1,1,0,1,1,1,1], | |
'Π': [1,1,1,1,0,1,1,0,1,1,0,1], | |
'Ρ': [1,1,1,1,0,1,1,1,1,1,0,0], | |
'Σ': [1,1,1,1,0,0,0,1,0,1,1,1], | |
'Τ': [1,1,1,0,1,0,0,1,0,0,1,0], | |
'Υ': [1,0,1,1,0,1,0,1,0,0,1,0], | |
'Φ': [0,1,0,1,1,1,1,0,1,1,1,1,0,1,0], | |
'Χ': [1,0,1,0,1,0,1,0,1,1,0,1], | |
'Ψ': [1,1,1,1,1,1,1,1,1,0,1,0], | |
'Ω': [1,1,1,1,0,1,0,1,0,1,1,1], | |
'α': [0,0,0,0,1,1,1,0,1,0,1,1], | |
'β': [1,1,0,1,1,0,1,0,1,1,1,0,1,0,0], | |
'γ': [0,0,0,1,0,0,1,0,1,1,1,0,0,1,0], | |
'δ': [0,0,1,0,1,0,1,0,1,0,1,0], | |
'ε': [0,0,0,0,1,1,1,1,0,0,1,1], | |
'ζ': [1,1,1,0,0,1,0,1,0,0,0,1,0,1,0], | |
'η': [0,0,0,1,1,0,1,0,1,1,0,1,0,0,1], | |
'θ': [0,1,0,1,0,1,1,1,1,0,1,0], | |
'ι': [0,0,0,0,1,0,0,1,0,0,0,1], | |
'κ': [0,0,0,1,0,1,1,1,0,1,0,1], | |
'λ': [1,0,0,0,1,0,0,1,1,1,0,1], | |
'μ': [0,0,0,1,0,1,1,0,1,1,1,0,1,0,0], | |
'ν': [0,0,0,1,0,1,0,1,1,0,1,0], | |
'ξ': [0,1,1,1,0,0,0,1,0,1,0,0,0,1,0], | |
'ο': [0,0,0,0,1,0,1,0,1,0,1,0], | |
'π': [0,0,0,1,1,1,1,0,1,1,0,1], | |
'ρ': [0,0,0,0,1,0,1,0,1,1,1,0,1,0,0], | |
'ς': [0,0,0,0,1,1,1,0,0,0,1,1,0,0,1], | |
'σ': [0,0,0,0,1,1,1,0,1,0,1,0], | |
'τ': [0,0,0,1,1,1,0,1,0,0,0,1], | |
'υ': [0,0,0,1,0,1,1,0,1,1,1,0], | |
'φ': [0,1,0,0,1,0,1,0,1,1,1,1,0,1,0], | |
'χ': [1,0,0,0,1,1,0,1,0,1,0,1], | |
'ψ': [0,1,0,0,1,0,1,1,1,1,1,1,0,1,0], | |
'ω': [0,0,0,1,0,1,1,1,1,1,1,0], | |
'⁰': [1,1,0,1,1,0,1,1,0], | |
'¹': [0,1,0,0,1,0,0,1,0], | |
'²': [1,0,0,0,1,0,1,1,0], | |
'³': [1,1,0,0,1,0,1,1,0], | |
'⁴': [1,0,0,1,1,0,0,1,0], | |
'⁵': [1,1,0,1,0,0,0,1,0], | |
'⁶': [1,0,0,1,1,0,1,1,0], | |
'⁷': [1,1,0,0,1,0,0,1,0], | |
'⁸': [1,1,0,0,0,0,1,1,0], | |
'⁹': [1,1,0,1,1,0,0,1,0], | |
'₀': [0,0,0,1,1,0,1,1,0,1,1,0], | |
'₁': [0,0,0,0,1,0,0,1,0,0,1,0], | |
'₂': [0,0,0,1,0,0,0,1,0,1,1,0], | |
'₃': [0,0,0,1,1,0,0,1,0,1,1,0], | |
'₄': [0,0,0,1,0,0,1,1,0,0,1,0], | |
'₅': [0,0,0,1,1,0,1,0,0,0,1,0], | |
'₆': [0,0,0,1,0,0,1,1,0,1,1,0], | |
'₇': [0,0,0,1,1,0,0,1,0,0,1,0], | |
'₈': [0,0,0,1,1,0,0,0,0,1,1,0], | |
'₉': [0,0,0,1,1,0,1,1,0,0,1,0], | |
'#': [0,1,0,1,1,1,0,1,0,1,1,1,0,1,0], | |
} | |
def array_to_polygons(bits, cols=3, size=100): | |
boxes = [] | |
for idx, bit in enumerate(bits): | |
if bit == 1: | |
x = (idx % cols) * size | |
y = (idx // cols) * size | |
boxes.append(box(x, -y, x + size, -y - size)) | |
return translate(unary_union(boxes, 0.5), xoff=0, yoff=400) | |
def create_glyph(font, char, bits): | |
glyph = font.createChar(ord(char)) | |
draw_shape(glyph.glyphPen(), array_to_polygons(bits)) | |
glyph.width = 400 | |
glyph.vwidth = 400 | |
def draw_shape(pen, shape): | |
contour = fontforge.contour() | |
if isinstance(shape, MultiPolygon): | |
for polygon in shape.geoms: | |
draw_polygon(pen, polygon) | |
elif isinstance(shape, Polygon): | |
draw_polygon(pen, shape) | |
contour.draw(pen) | |
pen = None | |
def draw_polygon(pen, polygon): | |
points = list(polygon.exterior.coords) | |
draw_line(pen, points) | |
for interior in polygon.interiors: | |
points = list(interior.coords) | |
draw_line(pen, points) | |
def draw_line(pen, points): | |
pen.moveTo(points[0]) | |
for point in points[1:]: | |
pen.lineTo(point) | |
pen.closePath() | |
font = fontforge.font() | |
font.familyname = "MiniGent" | |
font.fontname = "MiniGent-Regular" | |
font.fullname = "MiniGent Regular" | |
for char, bits in glyph_data.items(): | |
create_glyph(font, char, bits) | |
font.generate('MiniGent-Regular.ttf') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment