~kris/dots

srice

ref: e98f3b030dc24445bd55c68d95d2d81933fd68b3 srice/.config/conky/lean-conky/font/build -rw-r--r-- 5.7 KiB
e98f3b03 — Kris Yotam chore: sync local state after restore (push updates, no pull) a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/fontforge -lang=py
# vim: ft=python:ts=4:sw=4:et:ai:cin

# Build LeanConkyConfig font - requiring FontForge to run

import argparse
import logging
import sys
import os.path as osp
import tempfile
from glob import glob
from datetime import date
import fontforge as ff
import psMat

tmp_dir = tempfile.gettempdir()

# Font Awesome settings
FA_URL = (
    "https://github.com/FortAwesome/Font-Awesome/releases/download/"
    + "6.1.1/fontawesome-free-6.1.1-desktop.zip"
)
FA_DIR = osp.join(tmp_dir, "lcc_fontawesome")
FA_SUBSET = """
f007    #user
f013    #cog
f015    #home
f017    #clock
f019    #download
f01c    #inbox
f073    #calendar
f085    #cogs
f093    #upload
f0a0    #hdd
f0ac    #globe
f0e8    #sitemap
f108    #desktop
f1c0    #database
f1eb    #wifi
f233    #server
f293    #bluetooth
f2db    #microchip
f2f5    #sign-out-alt
f2f6    #sign-in-alt
f381    #cloud-download-alt
f382    #cloud-upload-alt
f3c5    #map-marker-alt
f538    #memory
f56e    #file-export
f56f    #file-import
f6ff    #network-wired
f7c2    #sd-card
"""

# Bootstrap font settings
FB_URL = "https://github.com/twbs/icons/raw/v1.8.2/font/fonts/bootstrap-icons.woff"
FB_FILE = osp.join(tmp_dir, "bootstrap-icons.woff")
FB_SUBSET = """
f6e2    #gpu-card
"""

# parse command line
parser = argparse.ArgumentParser(description="Build LeanConkyConfig font file.")
parser.add_argument(
    "-verbose", help="output debug information", action="count", default=0
)
parser.add_argument("-lcd-font", help="lcd font file", default="TRS-Million-mod.otf")
parser.add_argument("-output", help="output file", default="lean-conky-config.otf")
args = parser.parse_args()

# logger
logging.basicConfig(
    level=logging.DEBUG if args.verbose else logging.INFO,
    style="{",
    format="{asctime} {message}",
    stream=sys.stdout,
)
logging.info("Start build custom font")


def parse_subset(subset):
    parsed = []
    for l in subset.split("\n"):
        x = l.split("#", maxsplit=1)[0].strip()
        if x:
            parsed.append(int(x, base=16))
    return parsed


def copy_attrs(src, dst, attrs):
    for a in attrs:
        v = getattr(src, a)
        logging.debug("%s: %s => %s", a, getattr(dst, a), v)
        setattr(dst, a, v)


def merge_font(dst_font, src_font, selection=None):
    if selection:
        src_font.selection.select(*selection)
        dst_font.selection.select(*selection)
    else:
        src_font.selection.all()
        dst_font.selection.all()
    src_font.copy()
    dst_font.paste()


def copy_glyphnames(dst_font, src_font, unicodes):
    logging.debug(
        "Copy glyphnames: {} -> {}".format(src_font.fontname, dst_font.fontname)
    )
    logging.debug("---------------------")
    common_codes = [k for k in unicodes if k in src_font and k in dst_font]
    for k in common_codes:
        src_name = src_font[k].glyphname
        logging.debug("{} -> {}".format(src_name, dst_font[k].glyphname))
        dst_font[k].glyphname = src_name
    logging.debug("---------------------")


# fetch FA if needed
if osp.isdir(FA_DIR):
    logging.debug("FA font cache found: {}".format(FA_DIR))
else:
    fa_download = FA_DIR + ".zip"
    if osp.isfile(fa_download):
        logging.debug("FA font already downloaded: {}".format(fa_download))
    else:
        import urllib.request

        urllib.request.urlretrieve(FA_URL, fa_download)
        logging.info("Downloaded FA font: {}".format(fa_download))

    import zipfile

    with zipfile.ZipFile(fa_download, "r") as z:
        z.extractall(FA_DIR, [f for f in z.namelist() if f.endswith(".otf")])
        logging.debug("Extracted .otf files from FA")

# subset and merge fonts
# FA solid
fa = glob(osp.join(FA_DIR, "**/*Solid*"), recursive=True)
if fa:
    fa = ff.open(fa[0])
else:
    raise FileNotFoundError("FA-Solid font not found")

nf = ff.font()
nf.fontname = nf.familyname = nf.fullname = "LeanConkyConfig"
nf.version = date.today().strftime("%Y%m%d")
with open("./LICENSE", "r") as f:
    nf.copyright = f.read().strip()

logging.info("Copy essential FA font attributes")
copy_attrs(fa, nf, ["encoding", "em", "ascent", "descent"])

fa_subset = parse_subset(FA_SUBSET)
sel = [("unicode", "singletons")] + fa_subset
logging.info("Subset and merge FA-Solid font")
merge_font(nf, fa, sel)
copy_glyphnames(nf, fa, fa_subset)

# FA brands
fa = glob(osp.join(FA_DIR, "**/*Brands*"), recursive=True)
if fa:
    logging.info("Subset and merge FA-Brands font")
    fa = ff.open(fa[0])
    merge_font(nf, fa, sel)
    copy_glyphnames(nf, fa, fa_subset)
else:
    raise FileNotFoundError("FA-Brands font not found")


# Bootstrap font
if osp.isfile(FB_FILE):
    logging.debug("Booststrap font already downloaded: {}".format(FB_FILE))
else:
    import urllib.request

    urllib.request.urlretrieve(FB_URL, FB_FILE)
    logging.info("Downloaded Bootstrap font: {}".format(FB_FILE))
fb = ff.open(FB_FILE)
fb.selection.all()
fb.transform(psMat.compose(psMat.scale(1.18 * nf.em / fb.em), psMat.translate(0, -100)))
fb_subset = parse_subset(FB_SUBSET)
sel = [("unicode", "singletons")] + fb_subset
logging.info("Subset and merge Bootstrap font")
merge_font(nf, fb, sel)
copy_glyphnames(nf, fb, fb_subset)

# LCD font (modified TRS Million by default)
logging.info("Subset and merge LCD font file: {}".format(args.lcd_font))
cf = ff.open(args.lcd_font)
cf.selection.all()
cf.transform(psMat.scale(float(nf.em) / cf.em))
merge_font(nf, cf, [" "])
merge_font(nf, cf, [("more", "ranges"), ".", ":"])  # 0-9 included
merge_font(nf, cf, [("more", "ranges"), "A", "Z"])
merge_font(nf, cf, [("more", "ranges"), "a", "z"])

# adjust specific icon
nf.selection.select(0xF2DB)  # cpu (microchip)
nf.transform(psMat.compose(psMat.scale(1.15), psMat.translate(-20, 0)))

# save the final work
nf.generate(args.output)
logging.info("Generated font file: {}".format(args.output))