font.ttf 3.000: all five cabinet atlases (adds Simplified Chinese and Korean) #32
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -44,7 +44,7 @@ def _trace(job):
|
|||||||
return cp, int(round(w * scale)), None # blank: advance only
|
return cp, int(round(w * scale)), None # blank: advance only
|
||||||
big = np.array(Image.fromarray(a).resize((w * UPSCALE, h * UPSCALE), Image.BICUBIC)) < 128 # potracer: True = white
|
big = np.array(Image.fromarray(a).resize((w * UPSCALE, h * UPSCALE), Image.BICUBIC)) < 128 # potracer: True = white
|
||||||
path = potrace.Bitmap(big).trace(turdsize=4,
|
path = potrace.Bitmap(big).trace(turdsize=4,
|
||||||
alphamax=1.0, opticurve=True, opttolerance=0.5)
|
alphamax=1.0, opticurve=True, opttolerance=0.2)
|
||||||
k = scale / UPSCALE
|
k = scale / UPSCALE
|
||||||
def P(p): return (p.x * k, (baseline_px * UPSCALE - p.y) * k)
|
def P(p): return (p.x * k, (baseline_px * UPSCALE - p.y) * k)
|
||||||
contours = []
|
contours = []
|
||||||
@@ -62,13 +62,18 @@ def main():
|
|||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
ap.add_argument('atlas_dir'); ap.add_argument('out')
|
ap.add_argument('atlas_dir'); ap.add_argument('out')
|
||||||
ap.add_argument('--order', default='jp,tw,cn,kr,en')
|
ap.add_argument('--order', default='jp,tw,cn,kr,en')
|
||||||
|
ap.add_argument('--han-order', default='', help='separate priority for CJK ideographs (U+2E80-9FFF, F900-FAFF, 20000+); --order then applies to everything else')
|
||||||
ap.add_argument('--jobs', type=int, default=max(1, os.cpu_count() - 4))
|
ap.add_argument('--jobs', type=int, default=max(1, os.cpu_count() - 4))
|
||||||
ap.add_argument('--limit', type=int, default=0, help='debug: glyphs per atlas')
|
ap.add_argument('--limit', type=int, default=0, help='debug: glyphs per atlas')
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
langs = args.order.split(',')
|
langs = args.order.split(',')
|
||||||
|
han_langs = args.han_order.split(',') if args.han_order else langs
|
||||||
|
def is_han(cp): return 0x2E80 <= cp <= 0x9FFF or 0xF900 <= cp <= 0xFAFF or cp >= 0x20000
|
||||||
|
def rank(lang, cp): return (han_langs if is_han(cp) else langs).index(lang) if lang in (han_langs if is_han(cp) else langs) else 99
|
||||||
|
|
||||||
taken = {} # cp -> (advance, contours or None, lang)
|
taken = {} # cp -> (advance, contours or None, lang)
|
||||||
for lang in langs:
|
all_langs = list(dict.fromkeys(langs + han_langs))
|
||||||
|
for lang in all_langs:
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
glyphs, attr = parse_xml(os.path.join(args.atlas_dir, f'{lang}_64.xml'))
|
glyphs, attr = parse_xml(os.path.join(args.atlas_dir, f'{lang}_64.xml'))
|
||||||
im = Image.open(os.path.join(args.atlas_dir, f'{lang}_64.dds'))
|
im = Image.open(os.path.join(args.atlas_dir, f'{lang}_64.dds'))
|
||||||
@@ -89,7 +94,7 @@ def main():
|
|||||||
alpha_path = os.path.join(args.atlas_dir, f'_{lang}_alpha.npy')
|
alpha_path = os.path.join(args.atlas_dir, f'_{lang}_alpha.npy')
|
||||||
np.save(alpha_path, A)
|
np.save(alpha_path, A)
|
||||||
jobs = [(cp, u, v, w, h, scale, baseline_px) for cp, (u, v, w, h) in sorted(glyphs.items())
|
jobs = [(cp, u, v, w, h, scale, baseline_px) for cp, (u, v, w, h) in sorted(glyphs.items())
|
||||||
if cp not in taken or taken[cp][1] is None and cp not in (0x20, 0x3000, 0xA0)]
|
if (cp not in taken or taken[cp][1] is None and cp not in (0x20, 0x3000, 0xA0) or rank(lang, cp) < rank(taken[cp][2], cp))]
|
||||||
if args.limit: jobs = jobs[:args.limit]
|
if args.limit: jobs = jobs[:args.limit]
|
||||||
got = 0
|
got = 0
|
||||||
with Pool(args.jobs, initializer=_init, initargs=(alpha_path,)) as pool:
|
with Pool(args.jobs, initializer=_init, initargs=(alpha_path,)) as pool:
|
||||||
@@ -98,7 +103,7 @@ def main():
|
|||||||
if cp in (0x20, 0x3000, 0xA0) and cp not in taken:
|
if cp in (0x20, 0x3000, 0xA0) and cp not in taken:
|
||||||
taken[cp] = (adv, None, lang)
|
taken[cp] = (adv, None, lang)
|
||||||
continue
|
continue
|
||||||
if cp in taken and taken[cp][1] is not None: continue
|
if cp in taken and taken[cp][1] is not None and rank(lang, cp) >= rank(taken[cp][2], cp): continue
|
||||||
taken[cp] = (adv, contours, lang); got += 1
|
taken[cp] = (adv, contours, lang); got += 1
|
||||||
os.remove(alpha_path)
|
os.remove(alpha_path)
|
||||||
print(f'{lang}_64: fontPoint {attr["fontPoint"]} scale {scale:.2f} baseline {baseline_px:.1f}px '
|
print(f'{lang}_64: fontPoint {attr["fontPoint"]} scale {scale:.2f} baseline {baseline_px:.1f}px '
|
||||||
@@ -117,7 +122,7 @@ def main():
|
|||||||
adv, contours, _ = taken[cp]
|
adv, contours, _ = taken[cp]
|
||||||
pen = TTGlyphPen(None)
|
pen = TTGlyphPen(None)
|
||||||
if contours:
|
if contours:
|
||||||
qpen = Cu2QuPen(pen, max_err=2.0, reverse_direction=False)
|
qpen = Cu2QuPen(pen, max_err=1.0, reverse_direction=False)
|
||||||
for segs in contours:
|
for segs in contours:
|
||||||
for s in segs:
|
for s in segs:
|
||||||
if s[0] == 'M': qpen.moveTo(s[1])
|
if s[0] == 'M': qpen.moveTo(s[1])
|
||||||
|
|||||||
Reference in new issue
Block a user