monolisa-nerdfont-patch/src/glyphs/octicons/generate

202 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env python3
# coding=utf8
import sys
import os
import re
import subprocess
import fontforge
# Double-quotes required here, for version-bump.sh:
version = "2.3.3"
archive = "v18.3.0.tar.gz"
vectorsdir = "icons"
fontdir = "."
fontfile = "octicons.ttf"
glyphsetfile = "i_oct.sh"
glyphsetsdir = "../../../bin/scripts/lib"
subset = "-16" # use 16 px subset if possible
subset_other = "-24" # use 24 px subset otherwise
def renamer(old_name):
"""Return new equivalent icon name"""
return {
"trashcan": "trash",
"cloud-download": "download",
"cloud-upload": "upload",
"clippy": "paste",
"mail-read": "read",
"primitive-dot": "dot-fill",
"primitive-square": "square-fill",
"settings": "sliders",
"dashboard": "meter",
"paintcan": "paintbrush",
}.get(old_name, old_name)
def addIcon(codepoint, name, filename):
"""Add one outline file and rescale/move"""
dBB = [120, 0, 1000 - 120, 900] # just some nice sizes
filename = os.path.join(vectorsdir, filename)
glyph = font.createChar(codepoint, name)
glyph.importOutlines(filename)
glyph.manualHints = True
def createGlyphInfo(icon_datasets, filepathname, into):
"""Write the glyphinfo file"""
with open(filepathname, "w", encoding="utf8") as f:
f.write("#!/usr/bin/env bash\n")
f.write(intro)
f.write("# Script Version: (autogenerated)\n")
f.write('test -n "$__i_oct_loaded" && return || __i_oct_loaded=1\n')
for _, codepoint, name in icon_datasets:
codepoint = int(codepoint, 16)
f.write(
"i='{}' i_oct_{}=$i\n".format(chr(codepoint), name.replace("-", "_"))
)
f.write("unset i\n")
print("\nReading mapping file")
old_mapping = []
with open("mapping", "r") as f:
for line in f.readlines():
if line.startswith("#"):
continue
old_mapping.append(tuple(re.split(" +", line.strip())))
print("Found {} entries".format(len(old_mapping)))
old_mapping.sort(key=(lambda x: x[0]))
print('Fetching octicons archive "{}"\n'.format(archive))
if subprocess.call(
"curl -OL https://github.com/primer/octicons/archive/" + archive, shell=True
):
sys.exit("Error fetching octicons archive")
print("\nUnpacking octicons archive")
if subprocess.call(
"rm -rf icons octicons-* && tar zxf *.gz && mv octicons-*/icons . && rm -rf octicons-*",
shell=True,
):
sys.exit("Error unpacking archive")
svgs = os.listdir(vectorsdir)
print("Found {} svgs".format(len(svgs)))
names = {
s[0 : -len("-xx.svg")]
for s in svgs
if s.endswith(subset + ".svg") or s.endswith(subset_other + ".svg")
}
print("Found {} icons after de-duplicating\n".format(len(names)))
num_found = 0
num_missing = 0
misslist = ""
renamelist = ""
freeslots = []
new_mapping = []
for i, j, old_n in old_mapping:
if old_n in names:
names.remove(old_n)
new_mapping.append((i, j, old_n))
num_found += 1
continue
new_n = renamer(old_n)
if new_n in names:
renamelist += "Renamed {} -> {}\n".format(old_n, new_n)
names.remove(new_n)
new_mapping.append((i, j, new_n))
num_found += 1
continue
misslist += "Missing {}\n".format(old_n)
freeslots.append((i, j))
num_missing += 1
print(renamelist)
print(misslist)
print(
"Found {} (of {}, missing {}) and new {}".format(
num_found, len(old_mapping), num_missing, len(names)
)
)
names = list(names)
names.sort()
for n in list(names):
if len(freeslots) == 0:
break
i, j = freeslots[0]
new_mapping.append((i, j, n))
names.remove(n)
freeslots = freeslots[1:]
print("Filled in missing, remaining new {}".format(len(names)))
i_max = 0
j_max = 0
for i, j, _ in new_mapping:
i = int(i, 16)
j = int(j, 16)
if i > i_max:
i_max = i
if j > j_max:
j_max = j
for n in names:
i_max += 1
j_max += 1
new_mapping.append(("{:X}".format(i_max), "{:X}".format(j_max), n))
print("Appended remaining new, total new mapping {}".format(len(new_mapping)))
new_mapping.sort(key=(lambda x: x[0]))
with open("mapping", "w") as f:
for i, j, n in new_mapping:
f.write("{} {} {}\n".format(i, j, n))
font = fontforge.font()
font.fontname = "OcticonsNerdFont-Regular"
font.fullname = "Octicons Nerd Font Regular"
font.familyname = "Octicons Nerd Font"
font.em = 2048
font.encoding = "UnicodeFull"
# Add valid space glyph to avoid "unknown character" box on IE11
glyph = font.createChar(32)
glyph.width = 200
font.sfntRevision = None # Auto-set (refreshed) by fontforge
font.version = version
font.copyright = "GitHub Inc."
font.appendSFNTName("English (US)", "Version", archive + "; " + version)
font.appendSFNTName(
"English (US)", "Vendor URL", "https://github.com/ryanoasis/nerd-fonts"
)
font.appendSFNTName("English (US)", "Copyright", "GitHub Inc.")
for codepoint, _, name in new_mapping:
codepoint = int(codepoint, 16)
filename = name + subset + ".svg"
if filename not in svgs:
filename = name + subset_other + ".svg"
addIcon(codepoint, name, filename)
num_icons = len(new_mapping)
print("Generating {} with {} glyphs".format(fontfile, num_icons))
font.generate(os.path.join(fontdir, fontfile), flags=("no-FFTM-table",))
codepoints = [int(p, 16) for _, p, _ in new_mapping]
intro = "# Octicons ({} icons)\n".format(num_icons)
intro += "# Codepoints: {:X}-{:X} with gaps\n".format(min(codepoints), max(codepoints))
intro += "# Nerd Fonts Version: {}\n".format(version)
print("Generating GlyphInfo {}".format(glyphsetfile))
createGlyphInfo(new_mapping, os.path.join(glyphsetsdir, glyphsetfile), intro)
print("Finished")