Created
July 19, 2025 20:30
-
-
Save damieng/2238a3eddc1cafab780937e969c56a94 to your computer and use it in GitHub Desktop.
Spectrum font conversion in FontLab 5
This file contains hidden or 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
#FLM: ZX Conversion | |
# Create TTF from 8x8 ZX BDF | |
## Set metadata | |
import os | |
font = fl.font | |
# Base name on filename | |
fontName = os.path.basename(os.path.splitext(font.file_name)[0]).strip() | |
nameParts = fontName.split() | |
isBold = True if "Bold" in nameParts else False | |
isItalic = True if "Italic" in nameParts else False | |
styleNames = [] | |
font.font_style = 0 | |
font.weight = "Regular" | |
font.weight_code = 400 | |
# Typical font characteristics | |
pixels_descender = 1 # Pixels for the descender | |
pixels_lower = 5 # Lower-case x-height (acxo) | |
pixels_upper = 7 # Upper-case height (ABCD) | |
pixels_ascender = pixels_upper | |
# Pixel metrics | |
pixel_size_x = 100 | |
pixel_size_y = 100 | |
pixels_wide = 8 | |
pixels_high = 8 | |
# Calculations | |
height = pixel_size_y * 8 | |
width = pixel_size_x * 8 | |
# Set the font metrics | |
font.upm = height | |
font.ascender[0] = pixels_ascender * pixel_size_y | |
font.descender[0] = 0 - (pixels_descender * pixel_size_y) | |
font.cap_height[0] = pixels_upper * pixel_size_y | |
font.x_height[0] = pixels_lower * pixel_size_y | |
font.default_width[0] = width | |
font.underline_position = font.descender[0] | |
font.underline_thickness = pixel_size_y | |
font.is_fixed_pitch = 1 | |
font.panose[3] = 0 | |
if isBold: | |
styleNames.append("Bold") | |
nameParts.remove("Bold") | |
font.font_style += 32 | |
font.weight = "Bold" | |
font.weight_code = 700 | |
if isItalic: | |
styleNames.append("Italic") | |
nameParts.remove("Italic") | |
font.font_style += 1 | |
if styleNames: | |
styleName = " ".join(styleNames) | |
else: | |
styleName = "Regular" | |
familyName = " ".join(nameParts) | |
fullName = familyName + " " + styleName | |
# Set all standard names | |
font.family_name = familyName | |
font.style_name = styleName | |
font.font_name = familyName.replace(' ', '') + "-" + styleName.replace(' ', '') | |
font.full_name = fullName | |
font.menu_name = familyName | |
font.apple_name = fullName if isBold or isItalic else familyName | |
# Personalized creator info | |
font.designer = "Damien Guard" | |
font.designer_url = "https://damieng.com" | |
font.year = 2019 | |
font.copyright = "Copyright 2019 Damien Guard." | |
font.vendor = "ENVY" | |
font.vendor_url = "https://envytech.com" | |
# Set OpenType & TrueType data | |
font.pref_family_name = familyName | |
font.pref_style_name = styleName | |
font.mac_compatible = fullName | |
font.tt_u_id = font.designer.replace(' ','') + ": " + fullName + ": " + str(font.year) | |
fl.UpdateFont() | |
## Clear font | |
glyphs = font.glyphs | |
for glyph in reversed(glyphs): | |
del glyphs[glyph.index] | |
## Index mode | |
fl.CallCommand(33209) | |
## Import BDF to background | |
fl.CallCommand(33911) | |
## Trace BDF background | |
fl.CallCommand(32873) | |
fl.CallCommand(33925) | |
## Remap indexes to correct location | |
for i in range(32, len(glyphs)): | |
glyphs[i].unicode = i | |
font.GenerateNames() | |
glyphs[i].width = width | |
## Remap indexes to correct location | |
for i in range(32, len(glyphs)): | |
glyphs[i].unicode = i | |
font.GenerateNames() | |
glyphs[i].width = width | |
fl.UpdateFont() | |
## Back to names mode | |
fl.CallCommand(33208) | |
## Remove empty glyphs | |
namesToKeep = [ '.notdef', 'NULL', 'CR', 'space' ] | |
for glyph in reversed(glyphs): | |
if not glyph.nodes and not glyph.components: | |
if not glyph.name in namesToKeep: | |
del glyphs[font.FindGlyph(glyph.name)] | |
fl.UpdateFont() | |
## Save & generate | |
ttfname = os.path.splitext(font.file_name)[0] + ".ttf" | |
fl.GenerateFont(ftTRUETYPE, ttfname) | |
fl.Save(font.file_name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment