diff options
| author | yum <yum.food.vr@gmail.com> | 2022-11-08 00:09:59 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2022-11-08 00:09:59 -0800 |
| commit | 2efc87a7180ec6e92127d22d1a3eb8c44fd392db (patch) | |
| tree | 0c8c6ace7d3b3752cdc67ee98bbb43a9ecec18cd /generate_fonts.py | |
| parent | 77c6f366b2f81c60ed67e2fa6dc92df451e4229c (diff) | |
Update fonts
English, Japanese, Chinese, and Korean should look much better now.
French, German, and Spanish look like shit now, because I haven't
figured out how to best make Noto Sans stay within its bounding box.
* Use Noto Sans for most things
* Simplify how we enable unicode blocks & assign fonts to them
* Increase string matching window to 300. Works better in real-world
test.
Diffstat (limited to 'generate_fonts.py')
| -rw-r--r-- | generate_fonts.py | 127 |
1 files changed, 91 insertions, 36 deletions
diff --git a/generate_fonts.py b/generate_fonts.py index c21382d..3c3ffb0 100644 --- a/generate_fonts.py +++ b/generate_fonts.py @@ -6,62 +6,117 @@ import math # Use a power of 2 pixels per character so we can evenly divide the plane. font_pixels = 128 -font = ImageFont.truetype("unifont-15.0.01.ttf", font_pixels) -font_half_sz = ImageFont.truetype("unifont-15.0.01.ttf", int(font_pixels / 2)) +full_ratio = 0.75 +half_ratio = 0.5 +full_sz = int(font_pixels * full_ratio) +half_sz = int(font_pixels * half_ratio) +layout_engine = ImageFont.Layout.BASIC + +unifont = ImageFont.truetype("Fonts/unifont-15.0.01.ttf", full_sz, layout_engine=layout_engine) +unifont_half = ImageFont.truetype("Fonts/unifont-15.0.01.ttf", half_sz, layout_engine=layout_engine) + +noto_sans_mono = ImageFont.truetype("Fonts/Noto_Sans_Mono/NotoSansMono-VariableFont_wdth,wght.ttf", full_sz, layout_engine=layout_engine) + +noto_sans_sc_half = ImageFont.truetype("Fonts/Noto_Sans_Simplified_Chinese/NotoSansSC-Regular.otf", half_sz, layout_engine=layout_engine) + +noto_sans_kr_half = ImageFont.truetype("Fonts/Noto_Sans_Korean/NotoSansKR-Regular.otf", half_sz, layout_engine=layout_engine) n_rows = 64 n_cols = 128 -def allow_range(allowlist, lo, hi): - for i in range(lo, hi + 1): - allowlist.add(i) +class FontInfo: + def __init__(self, font, dy): + self.font = font + self.dy = dy + +def allow_range(allowlist, lo_hi, font = None, dy = 0): + for i in range(lo_hi[0], lo_hi[1] + 1): + allowlist[i] = FontInfo(font, dy) def ban_range(allowlist, lo, hi): for i in range(lo, hi + 1): - allowlist.remove(i) -allowlist = set() + del allowlist[i] +allowlist = {} # ASCII -allow_range(allowlist, 32, 126) +basic_latin = (32, 126) +allow_range(allowlist, basic_latin, font=noto_sans_mono, dy = -20) # Latin-1 supplement -allow_range(allowlist, 0x00A1, 255) +latin_1_supplement = (0x00A1, 0x00ff) +allow_range(allowlist, latin_1_supplement, font = noto_sans_mono) # Latin extended-A -allow_range(allowlist, 0x0100, 0x017F) +latin_extended_a = (0x0100, 0x017f) +allow_range(allowlist, latin_extended_a, font = noto_sans_mono) # Latin extended-B -allow_range(allowlist, 0x0180, 0x024F) +latin_extended_b = (0x0180, 0x024f) +allow_range(allowlist, latin_extended_b, font = noto_sans_mono) # Spacing modifier letters -allow_range(allowlist, 0x0250, 0x02AF) +ipa_extensions = (0x0250, 0x02af) +allow_range(allowlist, ipa_extensions, font = unifont) # Greek and Coptic -allow_range(allowlist, 880, 1023) +greek = (0x0370, 0x03ff) +allow_range(allowlist, greek, font = noto_sans_mono) ban_range(allowlist, 0x0378, 0x03a2) # Cyrillic -allow_range(allowlist, 0x0400, 0x04FF) +cyrillic = (0x0400, 0x04ff) +allow_range(allowlist, cyrillic, font = unifont) # Currency symbols -allow_range(allowlist, 0x20A0, 0x20C0) +currency_symbols = (0x20a0, 0x20c0) +allow_range(allowlist, currency_symbols, font = noto_sans_mono) -# Japanese -# Punctuation -allow_range(allowlist, 0x3000, 0x303F) -# Hiragana -allow_range(allowlist, 0x3041, 0x30FF) +# CJK +# +hangul_jamo = (0x1100, 0x11FF) +allow_range(allowlist, hangul_jamo, font = noto_sans_kr_half) +# +general_punctuation = (0x2000, 0x206f) +allow_range(allowlist, general_punctuation, font = noto_sans_mono) +# +kangxi_radicals = (0x2f00, 0x2fdf) +allow_range(allowlist, kangxi_radicals, font = noto_sans_sc_half) +# +cjk_symbols_and_punctuation = (0x3000, 0x303f) +allow_range(allowlist, cjk_symbols_and_punctuation, font = noto_sans_sc_half) +# +hiragana = (0x3041, 0x309f) +allow_range(allowlist, hiragana, font = noto_sans_sc_half) ban_range(allowlist, 0x3097, 0x3098) -# Katakana -allow_range(allowlist, 0x30A0, 0x30FF) -# CJK Unified Ideographs (Kanji) -allow_range(allowlist, 0x4E00, 0x9FFF) -# CJK Unified Ideographs extension A (rare Kanji) -allow_range(allowlist, 0x3400, 0x4dbf) +# +katakana = (0x30a0, 0x30ff) +allow_range(allowlist, katakana, font = noto_sans_sc_half) +# +hangul_compatibility_jamo = (0x3130, 0x318f) +allow_range(allowlist, hangul_compatibility_jamo, font = noto_sans_sc_half) +# +enclosed_cjk_letters_and_months = (0x3200, 0x32FF) +allow_range(allowlist, enclosed_cjk_letters_and_months, font = noto_sans_sc_half) +# +cjk_compatibility = (0x3300, 0x33ff) +allow_range(allowlist, cjk_compatibility, font = noto_sans_sc_half) +# +cjk_unified_extension_a = (0x3400, 0x4dbf) +allow_range(allowlist, cjk_unified_extension_a, font = noto_sans_sc_half) +# +cjk_ideographs = (0x4e00, 0x9fff) +allow_range(allowlist, cjk_ideographs, font = noto_sans_sc_half) +# +hangul_syllables = (0xAC00, 0xD7A3) +allow_range(allowlist, hangul_syllables, font = noto_sans_kr_half) +# +halfwidth_and_fullwidth = (0xff00, 0xffef) +allow_range(allowlist, halfwidth_and_fullwidth, font = noto_sans_sc_half) -# Korean -allow_range(allowlist, 0x1100, 0x11FF) -allow_range(allowlist, 0xAC00, 0xD7A3) +def in_range(x, range_pair) -> bool: + return x >= range_pair[0] and x <= range_pair[1] max_char = max(allowlist) +print("max char: {}".format(max_char)) +print("num chars: {}".format(len(allowlist))) total_rows = math.ceil(max_char / n_cols) print("total rows {}".format(total_rows)) total_textures = math.ceil(total_rows / n_rows) print("total textures {}".format(total_textures)) for nth_texture in range(0, total_textures): - # Create an 8K grayscale ("L") image + # Create an 8K grayscale ("L") or black and white ("1") image image = Image.new(mode="1", size=(8192,8192), color=0) draw = ImageDraw.Draw(image) @@ -73,18 +128,18 @@ for nth_texture in range(0, total_textures): # Generate the unicode character for this spot. n = row * n_cols + col char = None - if n in allowlist: + font_info = None + if n in allowlist.keys(): char = chr(n) + font_info = allowlist[n] else: char = " " + font_info = FontInfo(unifont, 0) # Hack: Chinese, Japanese, and Korean characters are all double # width and are all on textures [1,6]. To fit them in the same # grid, we use a half-size font. - if nth_texture == 0: - draw.text((col * font_pixels / 2, (row - row_begin) * font_pixels), char, font=font, fill=255) - else: - draw.text((col * font_pixels / 2, (row - row_begin) * font_pixels), char, - font=font_half_sz, fill=255) + draw.text((col * font_pixels / 2, (row - row_begin) * font_pixels + + font_info.dy), char, font=font_info.font, fill=255) image.save("font-%01d.png" % nth_texture) |
