From 925016fc05734b2cbac4cddc6ddf939efde0113f Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 21:55:43 +0700 Subject: [PATCH 01/11] generate: allow to specify where to place diacritics Various scripts have diacritics on positions other than the top of base characters. This commit adds support for the (optional) `placement` key in diacritic.json, allowing diacritics to be placed in any of the four positions: above, below, to the left, and to the right of the glyph. The default when not specified is "above". The placement respects the spacing specified by the `diacriticSpace` key in characters.json. --- src/monocraft.py | 57 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/src/monocraft.py b/src/monocraft.py index 5421b8e..0147db3 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -265,21 +265,64 @@ def generateImage(character): kw.update(other[1]) image = image | other[0] if "diacritic" in character: - diacritic = diacritics[character["diacritic"]] - arr = diacritic["pixels"] - x = image.x - y = findHighestY(image) + 1 - if "diacriticSpace" in character: - y += int(character["diacriticSpace"]) - image = image | imageFromArray(arr, x, y) + image = addDiacritic(image, diacritics[character["diacritic"]], character["diacriticSpace"]) return (image, kw) +def addDiacritic(image, diacritic, spacing): + arr = diacritic["pixels"] + direction = [0, 1] + if "placement" in diacritic: + if "above" in diacritic["placement"]: + direction[1] = 1 + elif "below" in diacritic["placement"]: + direction[1] = -1 + if "left" in diacritic["placement"]: + direction[0] = -1 + elif "right" in diacritic["placement"]: + direction[0] = 1 + x, y = findBoundsInDirection(image, direction) + x += direction[0] + y += direction[1] + if spacing is not None: + x += int(spacing) * direction[0] + y += int(spacing) * direction[1] + return image | imageFromArray(arr, x, y) + +def findBoundsInDirection(image, direction): + if direction[0] == 0: x = image.x + elif direction[0] > 0: x = findHighestX(image) + elif direction[0] < 0: x = findLowestX(image) + + if direction[1] == 0: y = image.y + elif direction[1] > 0: y = findHighestY(image) + elif direction[1] < 0: y = findLowestY(image) + + return x, y + +def findHighestX(image): + for x in range(image.x_end - 1, image.x, -1): + for y in range(image.y, image.y_end): + if image[x, y]: + return x + return image.x +def findLowestX(image): + for x in range(image.x, image.x_end): + for y in range(image.y, image.y_end): + if image[x, y]: + return x + return image.x_end def findHighestY(image): for y in range(image.y_end - 1, image.y, -1): for x in range(image.x, image.x_end): if image[x, y]: return y return image.y +def findLowestY(image): + for y in range(image.y, image.y_end): + for x in range(image.x, image.x_end): + if image[x, y]: + return y + return image.y_end def imageFromArray(arr, x=0, y=0): return PixelImage( From e909d6f02a684aacfa16ad0e23832a77ac9267ba Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 22:14:27 +0700 Subject: [PATCH 02/11] generate: add support for multiple diacritics on a single glyph This allows to define a glyph with multiple diacritics attached. Currently overlaps are not handled (spacing is currently shared for all of them), meaning stacking diacritics in the same direction is not possible. --- src/monocraft.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/monocraft.py b/src/monocraft.py index 0147db3..ef4ee00 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -266,6 +266,9 @@ def generateImage(character): image = image | other[0] if "diacritic" in character: image = addDiacritic(image, diacritics[character["diacritic"]], character["diacriticSpace"]) + elif "diacritics" in character: + for diacritic in character["diacritics"]: + image = addDiacritic(image, diacritics[diacritic], character["diacriticSpace"]) return (image, kw) def addDiacritic(image, diacritic, spacing): From fea89b4e16807332251e36a3ab683af39b5d6292 Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 22:31:36 +0700 Subject: [PATCH 03/11] metadata: add various missing glyphs for Vietnamese This adds various missing glyphs for Vietnamese. Note that some characters require multiple diacritics in different positions. There is a hack in diacritics.json to force monocraft.py to include many glyphs in the generation step. For example, the glyph "LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW" contain two diacritics `circumflex` and `dot_below`. generate_diacritics.py parses this as containing one diacritic: `circumflex_and_dot_below`, which it will not find in diacritics.json without this hack, and thus the glyph will not be generated. For a proper fix, the logic to determine which diacritics should be considered (lines 37-38, generate_diacritics.py) should be fixed to consult the list in characters.json instead. --- src/characters.json | 759 ++++++++++++++++++++++++++++++++++++++++++++ src/diacritics.json | 124 ++++++++ 2 files changed, 883 insertions(+) diff --git a/src/characters.json b/src/characters.json index a9fc414..095ac5e 100644 --- a/src/characters.json +++ b/src/characters.json @@ -17935,5 +17935,764 @@ ], "group": "cjk_symbols_and_punctuation", "character": "〒" + }, + { + "codepoint": 272, + "name": "latin_capital_letter_d_with_stroke", + "pixels": [ + [0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1], + [1, 1, 1, 0, 0, 1], + [0, 1, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1], + [0, 1, 1, 1, 1, 0] + ], + "character": "Đ" + }, + { + "codepoint": 273, + "name": "latin_small_letter_d_with_stroke", + "pixels": [ + [0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 1, 1], + [0, 1, 1, 0, 1, 0], + [1, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 0] + ], + "character": "đ" + }, + { + "codepoint": 416, + "name": "latin_capital_letter_o_with_horn", + "pixels": [ + [0, 0, 0, 0, 0, 1], + [0, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 1, 1], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 0, 0] + ], + "character": "Ơ" + }, + { + "codepoint": 417, + "name": "latin_small_letter_o_with_horn", + "pixels": [ + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 1, 1], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 0, 0] + ], + "character": "ơ" + }, + { + "codepoint": 431, + "name": "latin_capital_letter_u_with_horn", + "pixels": [ + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 1, 1], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 0, 0] + ], + "character": "Ư" + }, + { + "codepoint": 432, + "name": "latin_small_letter_u_with_horn", + "pixels": [ + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 1, 1], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 0] + ], + "character": "ư" + }, + { + "codepoint": 7840, + "name": "latin_capital_letter_a_with_dot_below", + "character": "Ạ", + "reference": 65, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7841, + "name": "latin_small_letter_a_with_dot_below", + "character": "ạ", + "reference": 97, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7842, + "name": "latin_capital_letter_a_with_hook_above", + "character": "Ả", + "reference": 65, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7843, + "name": "latin_small_letter_a_with_hook_above", + "character": "ả", + "reference": 97, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7844, + "name": "latin_capital_letter_a_with_circumflex_and_acute", + "character": "Ắ", + "reference": 65, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7845, + "name": "latin_small_letter_a_with_circumflex_and_acute", + "character": "ắ", + "reference": 97, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7846, + "name": "latin_capital_letter_a_with_circumflex_and_grave", + "character": "Ằ", + "reference": 65, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7847, + "name": "latin_small_letter_a_with_circumflex_and_grave", + "character": "Ằ", + "reference": 97, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7848, + "name": "latin_capital_letter_a_with_circumflex_and_hook_above", + "character": "Ẳ", + "reference": 65, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7849, + "name": "latin_small_letter_a_with_circumflex_and_hook_above", + "character": "ẳ", + "reference": 97, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7850, + "name": "latin_capital_letter_a_with_circumflex_and_tilde", + "character": "Ẵ", + "reference": 65, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7851, + "name": "latin_small_letter_a_with_circumflex_and_tilde", + "character": "ẵ", + "reference": 97, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7852, + "name": "latin_capital_letter_a_with_circumflex_and_dot_below", + "character": "Ặ", + "reference": 65, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7853, + "name": "latin_small_letter_a_with_circumflex_and_dot_below", + "character": "ặ", + "reference": 97, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7854, + "name": "latin_capital_letter_a_with_breve_and_acute", + "character": "Ấ", + "reference": 65, + "diacritic": "breve_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7855, + "name": "latin_small_letter_a_with_breve_and_acute", + "character": "ấ", + "reference": 97, + "diacritic": "breve_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7856, + "name": "latin_capital_letter_a_with_breve_and_grave", + "character": "Ầ", + "reference": 65, + "diacritic": "breve_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7857, + "name": "latin_small_letter_a_with_breve_and_grave", + "character": "ầ", + "reference": 97, + "diacritic": "breve_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7858, + "name": "latin_capital_letter_a_with_breve_and_hook_above", + "character": "Ẩ", + "reference": 65, + "diacritic": "breve_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7859, + "name": "latin_small_letter_a_with_breve_and_hook_above", + "character": "ẩ", + "reference": 97, + "diacritic": "breve_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7860, + "name": "latin_capital_letter_a_with_breve_and_tilde", + "character": "ẫ", + "reference": 65, + "diacritic": "breve_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7861, + "name": "latin_small_letter_a_with_breve_and_tilde", + "character": "ẫ", + "reference": 97, + "diacritic": "breve_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7862, + "name": "latin_capital_letter_a_with_breve_and_dot_below", + "character": "ậ", + "reference": 65, + "diacritics": ["breve", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7863, + "name": "latin_small_letter_a_with_breve_and_dot_below", + "character": "ậ", + "reference": 97, + "diacritics": ["breve", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7864, + "name": "latin_capital_letter_e_with_dot_below", + "character": "Ẹ", + "reference": 69, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7865, + "name": "latin_small_letter_e_with_dot_below", + "character": "ẹ", + "reference": 101, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7866, + "name": "latin_capital_letter_e_with_hook_above", + "character": "Ẻ", + "reference": 69, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7867, + "name": "latin_small_letter_e_with_hook_above", + "character": "ẻ", + "reference": 101, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7870, + "name": "latin_capital_letter_e_with_circumflex_and_acute", + "character": "Ế", + "reference": 69, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7871, + "name": "latin_small_letter_e_with_circumflex_and_acute", + "character": "ế", + "reference": 101, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7872, + "name": "latin_capital_letter_e_with_circumflex_and_grave", + "character": "Ề", + "reference": 69, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7873, + "name": "latin_small_letter_e_with_circumflex_and_grave", + "character": "ề", + "reference": 101, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7874, + "name": "latin_capital_letter_e_with_circumflex_and_hook_above", + "character": "Ể", + "reference": 69, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7875, + "name": "latin_small_letter_e_with_circumflex_and_hook_above", + "character": "ể", + "reference": 101, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7876, + "name": "latin_capital_letter_e_with_circumflex_and_tilde", + "character": "Ễ", + "reference": 69, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7877, + "name": "latin_small_letter_e_with_circumflex_and_tilde", + "character": "ễ", + "reference": 101, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7878, + "name": "latin_capital_letter_e_with_circumflex_and_dot_below", + "character": "Ệ", + "reference": 69, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7879, + "name": "latin_small_letter_e_with_circumflex_and_dot_below", + "character": "ệ", + "reference": 101, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7880, + "name": "latin_capital_letter_i_with_hook_above", + "character": "Ỉ", + "reference": 73, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7881, + "name": "latin_small_letter_i_with_hook_above", + "character": "ỉ", + "reference": 105, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7882, + "name": "latin_capital_letter_i_with_dot_below", + "character": "Ị", + "reference": 73, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7883, + "name": "latin_small_letter_i_with_dot_below", + "character": "ị", + "reference": 105, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7884, + "name": "latin_capital_letter_o_with_dot_below", + "character": "Ọ", + "reference": 79, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7885, + "name": "latin_small_letter_o_with_dot_below", + "character": "ọ", + "reference": 111, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7886, + "name": "latin_capital_letter_o_with_hook_above", + "character": "Ỏ", + "reference": 79, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7887, + "name": "latin_small_letter_o_with_hook_above", + "character": "Ỏ", + "reference": 111, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7888, + "name": "latin_capital_letter_o_with_circumflex_and_acute", + "character": "Ố", + "reference": 79, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7889, + "name": "latin_small_letter_o_with_circumflex_and_acute", + "character": "ố", + "reference": 111, + "diacritic": "circumflex_and_acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7890, + "name": "latin_capital_letter_o_with_circumflex_and_grave", + "character": "Ồ", + "reference": 79, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7891, + "name": "latin_small_letter_o_with_circumflex_and_grave", + "character": "ồ", + "reference": 111, + "diacritic": "circumflex_and_grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7892, + "name": "latin_capital_letter_o_with_circumflex_and_hook_above", + "character": "Ổ", + "reference": 79, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7893, + "name": "latin_small_letter_o_with_circumflex_and_hook_above", + "character": "ổ", + "reference": 111, + "diacritic": "circumflex_and_hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7894, + "name": "latin_capital_letter_o_with_circumflex_and_tilde", + "character": "Ỗ", + "reference": 79, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7895, + "name": "latin_small_letter_o_with_circumflex_and_tilde", + "character": "ỗ", + "reference": 111, + "diacritic": "circumflex_and_tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7896, + "name": "latin_capital_letter_o_with_circumflex_and_dot_below", + "character": "Ộ", + "reference": 79, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7897, + "name": "latin_small_letter_o_with_circumflex_and_dot_below", + "character": "ộ", + "reference": 111, + "diacritics": ["circumflex", "dot_below"], + "diacriticSpace": 1 + }, + { + "codepoint": 7898, + "name": "latin_capital_letter_o_with_horn_and_acute", + "character": "Ớ", + "reference": 416, + "diacritic": "acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7899, + "name": "latin_small_letter_o_with_horn_and_acute", + "character": "ớ", + "reference": 417, + "diacritic": "acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7900, + "name": "latin_capital_letter_o_with_horn_and_grave", + "character": "Ờ", + "reference": 416, + "diacritic": "grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7901, + "name": "latin_small_letter_o_with_horn_and_grave", + "character": "ờ", + "reference": 417, + "diacritic": "grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7902, + "name": "latin_capital_letter_o_with_horn_and_hook_above", + "character": "Ở", + "reference": 416, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7903, + "name": "latin_small_letter_o_with_horn_and_hook_above", + "character": "ở", + "reference": 417, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7904, + "name": "latin_capital_letter_o_with_horn_and_tilde", + "character": "Ỡ", + "reference": 416, + "diacritic": "tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7905, + "name": "latin_small_letter_o_with_horn_and_tilde", + "character": "ỡ", + "reference": 417, + "diacritic": "tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7906, + "name": "latin_capital_letter_o_with_horn_and_dot_below", + "character": "Ợ", + "reference": 416, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7907, + "name": "latin_small_letter_o_with_horn_and_dot_below", + "character": "ợ", + "reference": 417, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7908, + "name": "latin_capital_letter_u_with_dot_below", + "character": "Ụ", + "reference": 85, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7909, + "name": "latin_small_letter_u_with_dot_below", + "character": "ụ", + "reference": 117, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7910, + "name": "latin_capital_letter_u_with_hook_above", + "character": "Ủ", + "reference": 85, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7911, + "name": "latin_small_letter_u_with_hook_above", + "character": "ủ", + "reference": 117, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7912, + "name": "latin_capital_letter_u_with_horn_and_acute", + "character": "Ứ", + "reference": 431, + "diacritic": "acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7913, + "name": "latin_small_letter_u_with_horn_and_acute", + "character": "ứ", + "reference": 432, + "diacritic": "acute", + "diacriticSpace": 1 + }, + { + "codepoint": 7914, + "name": "latin_capital_letter_u_with_horn_and_grave", + "character": "Ừ", + "reference": 431, + "diacritic": "grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7915, + "name": "latin_small_letter_u_with_horn_and_grave", + "character": "ừ", + "reference": 432, + "diacritic": "grave", + "diacriticSpace": 1 + }, + { + "codepoint": 7916, + "name": "latin_capital_letter_u_with_horn_and_hook_above", + "character": "Ử", + "reference": 431, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7917, + "name": "latin_small_letter_u_with_horn_and_hook_above", + "character": "ử", + "reference": 432, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7918, + "name": "latin_capital_letter_u_with_horn_and_tilde", + "character": "Ữ", + "reference": 431, + "diacritic": "tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7919, + "name": "latin_small_letter_u_with_horn_and_tilde", + "character": "ữ", + "reference": 432, + "diacritic": "tilde", + "diacriticSpace": 1 + }, + { + "codepoint": 7920, + "name": "latin_capital_letter_u_with_horn_and_dot_below", + "character": "Ự", + "reference": 431, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7921, + "name": "latin_small_letter_u_with_horn_and_dot_below", + "character": "ự", + "reference": 432, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7924, + "name": "latin_capital_letter_y_with_dot_below", + "character": "Ỵ", + "reference": 89, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7925, + "name": "latin_small_letter_y_with_dot_below", + "character": "ỵ", + "reference": 121, + "diacritic": "dot_below", + "diacriticSpace": 1 + }, + { + "codepoint": 7926, + "name": "latin_capital_letter_y_with_hook_above", + "character": "Ỷ", + "reference": 89, + "diacritic": "hook_above", + "diacriticSpace": 1 + }, + { + "codepoint": 7927, + "name": "latin_small_letter_y_with_hook_above", + "character": "ỷ", + "reference": 121, + "diacritic": "hook_above", + "diacriticSpace": 1 } ] \ No newline at end of file diff --git a/src/diacritics.json b/src/diacritics.json index 29e9ed3..39e5e7d 100644 --- a/src/diacritics.json +++ b/src/diacritics.json @@ -63,5 +63,129 @@ "pixels": [ [0, 0, 1, 0, 0] ] + }, + "breve_and_acute": { + "pixels": [ + [0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 0], + [0, 0, 1, 1, 0, 0] + ] + }, + "breve_and_grave": { + "pixels": [ + [0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 0], + [0, 1, 0, 0, 1, 0], + [0, 0, 1, 1, 0, 0] + ] + }, + "breve_and_hook_above": { + "pixels": [ + [0, 0, 0, 1, 0], + [0, 0, 0, 0, 1], + [0, 0, 0, 1, 0], + [0, 1, 0, 0, 1], + [0, 0, 1, 1, 0] + ] + }, + "breve_and_tilde": { + "pixels": [ + [0, 0, 0, 1, 0, 1], + [0, 0, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 0], + [0, 0, 1, 1, 0, 0] + ] + }, + "circumflex_and_acute": { + "pixels": [ + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 0, 0], + [0, 1, 0, 1, 0, 0] + ] + }, + "circumflex_and_grave": { + "pixels": [ + [1, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 1, 0] + ] + }, + "circumflex_and_hook_above": { + "pixels": [ + [0, 0, 0, 1, 0], + [0, 0, 0, 0, 1], + [0, 0, 0, 1, 0], + [0, 0, 1, 0, 0], + [0, 1, 0, 1, 0] + ] + }, + "circumflex_and_tilde": { + "pixels": [ + [0, 0, 1, 0, 1], + [0, 1, 0, 1, 0], + [0, 0, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 1, 0, 1, 0] + ] + }, + "dot_below": { + "placement": "below", + "pixels": [ + [0, 0, 1, 0, 0] + ] + }, + "hook_above": { + "pixels": [ + [0, 0, 1, 0, 0], + [0, 0, 0, 1, 0], + [0, 0, 1, 0, 0] + ] + }, + "circumflex_and_dot_below": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "breve_and_dot_below": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "horn_and_acute": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "horn_and_dot_below": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "horn_and_grave": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "horn_and_hook_above": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" + }, + "horn_and_tilde": { + "pixels": [ + [] + ], + "comment": "hack for generate_diacritics.py to include in glyph generation" } } \ No newline at end of file From d6836df2dfb0be7a7462d296fad09b14fda646fa Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 22:44:44 +0700 Subject: [PATCH 04/11] generate: add support for offsetting the diacritic This commit adds support for two optional keys in diacritics.json: offsetX and offsetY. This allows the glyph to be shifted relative to the base position. --- src/diacritics.json | 3 ++- src/monocraft.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/diacritics.json b/src/diacritics.json index 39e5e7d..478a901 100644 --- a/src/diacritics.json +++ b/src/diacritics.json @@ -113,7 +113,8 @@ [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0] - ] + ], + "offsetX": -1 }, "circumflex_and_hook_above": { "pixels": [ diff --git a/src/monocraft.py b/src/monocraft.py index ef4ee00..05101b0 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -286,6 +286,10 @@ def addDiacritic(image, diacritic, spacing): x, y = findBoundsInDirection(image, direction) x += direction[0] y += direction[1] + if "offsetX" in diacritic: + x += diacritic["offsetX"] + if "offsetY" in diacritic: + y += diacritic["offsetY"] if spacing is not None: x += int(spacing) * direction[0] y += int(spacing) * direction[1] From 4c6706dba9751be6d6f4f7567104d0fc40ccda7e Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 22:49:12 +0700 Subject: [PATCH 05/11] generate: raise glyph ascent height Some Vietnamese glyphs are very tall with their diacritics, which causes the top of them to sometimes be cut off in some programs. This raises the font ascent by 1 pixel size to accomodate those glyphs. As a side effect, however, this also messes with font sizing in a lot of programs. --- src/monocraft.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/monocraft.py b/src/monocraft.py index 05101b0..4f705fc 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -112,9 +112,9 @@ def generateFont(*, black=False, bold=False, semibold=False, light=False, extral font.encoding = "UnicodeFull" font.version = "4.0" font.weight = "Regular" - font.ascent = PIXEL_SIZE * 8 + font.ascent = PIXEL_SIZE * 9 font.descent = PIXEL_SIZE - font.em = PIXEL_SIZE * 9 + font.em = PIXEL_SIZE * 10 font.upos = -PIXEL_SIZE # Underline position font.addLookup("ligatures", "gsub_ligature", (), (("liga", (("dflt", ("dflt")), ("latn", ("dflt")))), )) From 6cb8acbe54c66c578484cea9fdfcfedafb9b799d Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:24:12 +0700 Subject: [PATCH 06/11] glyph: fix missing pixel on hook diacritic --- src/diacritics.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diacritics.json b/src/diacritics.json index 478a901..15851ed 100644 --- a/src/diacritics.json +++ b/src/diacritics.json @@ -83,7 +83,7 @@ }, "breve_and_hook_above": { "pixels": [ - [0, 0, 0, 1, 0], + [0, 0, 1, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 1, 0, 0, 1], @@ -118,7 +118,7 @@ }, "circumflex_and_hook_above": { "pixels": [ - [0, 0, 0, 1, 0], + [0, 0, 1, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], @@ -142,7 +142,7 @@ }, "hook_above": { "pixels": [ - [0, 0, 1, 0, 0], + [0, 1, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0] ] From 26c7b8eb1c9054386a26bd924658ec18669cda34 Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:28:30 +0700 Subject: [PATCH 07/11] glyph: change horn characters to be identical to Minecraft The original variant looks better in text, but is different from the font in-game. --- src/characters.json | 55 ++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/src/characters.json b/src/characters.json index 095ac5e..1c73ab1 100644 --- a/src/characters.json +++ b/src/characters.json @@ -17968,14 +17968,13 @@ "codepoint": 416, "name": "latin_capital_letter_o_with_horn", "pixels": [ - [0, 0, 0, 0, 0, 1], - [0, 1, 1, 1, 0, 1], - [1, 0, 0, 0, 1, 1], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [0, 1, 1, 1, 0, 0] + [0, 1, 1, 1, 0, 0, 1], + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 0], + [1, 0, 0, 0, 1, 0, 0], + [1, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 1, 0, 0, 0] ], "character": "Ơ" }, @@ -17983,13 +17982,11 @@ "codepoint": 417, "name": "latin_small_letter_o_with_horn", "pixels": [ - [0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0], - [0, 1, 1, 1, 0, 1], - [1, 0, 0, 0, 1, 1], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [0, 1, 1, 1, 0, 0] + [0, 1, 1, 1, 0, 0, 1], + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 1, 0, 0, 0] ], "character": "ơ" }, @@ -17997,15 +17994,13 @@ "codepoint": 431, "name": "latin_capital_letter_u_with_horn", "pixels": [ - [0, 0, 0, 0, 0, 1], - [0, 0, 0, 0, 0, 1], - [1, 0, 0, 0, 1, 1], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [0, 1, 1, 1, 0, 0] + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 0], + [1, 0, 0, 0, 1, 0, 0], + [1, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 1, 0, 0, 0] ], "character": "Ư" }, @@ -18013,13 +18008,11 @@ "codepoint": 432, "name": "latin_small_letter_u_with_horn", "pixels": [ - [0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1], - [1, 0, 0, 0, 1, 1], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 1, 0], - [0, 1, 1, 1, 1, 0] + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 1, 1, 0, 0] ], "character": "ư" }, From a66d7fffaf02d2b3a08e6d91f83316ddbc976228 Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:28:30 +0700 Subject: [PATCH 08/11] diacritic: offset diacritics to be identical to Minecraft The original variant looks better in text, but is different from the font in-game. --- src/diacritics.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/diacritics.json b/src/diacritics.json index 15851ed..1b1e201 100644 --- a/src/diacritics.json +++ b/src/diacritics.json @@ -97,7 +97,8 @@ [0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 1, 1, 0, 0] - ] + ], + "offsetY": -1 }, "circumflex_and_acute": { "pixels": [ @@ -105,7 +106,8 @@ [0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0], [0, 1, 0, 1, 0, 0] - ] + ], + "offsetX": -1 }, "circumflex_and_grave": { "pixels": [ @@ -113,8 +115,7 @@ [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0] - ], - "offsetX": -1 + ] }, "circumflex_and_hook_above": { "pixels": [ @@ -123,7 +124,8 @@ [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 1, 0] - ] + ], + "offsetX": -1 }, "circumflex_and_tilde": { "pixels": [ @@ -132,7 +134,8 @@ [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 0, 1, 0] - ] + ], + "offsetY": -1 }, "dot_below": { "placement": "below", From d00b9963a76df3d727172447441cdca3462e9a08 Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Mon, 19 Feb 2024 08:42:30 +0700 Subject: [PATCH 09/11] generate: bump ascent height for very taaaaall Vietnamese glyphs The last size bump did not take into account capital letters. --- src/monocraft.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/monocraft.py b/src/monocraft.py index 4f705fc..c22fb99 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -23,7 +23,7 @@ from polygonizer import PixelImage, generatePolygons from generate_continuous_ligatures import generate_continuous_ligatures -PIXEL_SIZE = 120 +PIXEL_SIZE = 80 characters = json.load(open("./characters.json")) diacritics = json.load(open("./diacritics.json")) @@ -112,9 +112,9 @@ def generateFont(*, black=False, bold=False, semibold=False, light=False, extral font.encoding = "UnicodeFull" font.version = "4.0" font.weight = "Regular" - font.ascent = PIXEL_SIZE * 9 + font.ascent = PIXEL_SIZE * 12 font.descent = PIXEL_SIZE - font.em = PIXEL_SIZE * 10 + font.em = PIXEL_SIZE * 13 font.upos = -PIXEL_SIZE # Underline position font.addLookup("ligatures", "gsub_ligature", (), (("liga", (("dflt", ("dflt")), ("latn", ("dflt")))), )) From 93a838222b45e8acc77fc3441956061374ea690e Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:53:44 +0700 Subject: [PATCH 10/11] generate: more descent --- src/monocraft.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/monocraft.py b/src/monocraft.py index c22fb99..8d75070 100644 --- a/src/monocraft.py +++ b/src/monocraft.py @@ -113,9 +113,9 @@ def generateFont(*, black=False, bold=False, semibold=False, light=False, extral font.version = "4.0" font.weight = "Regular" font.ascent = PIXEL_SIZE * 12 - font.descent = PIXEL_SIZE + font.descent = PIXEL_SIZE * 2 font.em = PIXEL_SIZE * 13 - font.upos = -PIXEL_SIZE # Underline position + font.upos = -PIXEL_SIZE * 2 # Underline position font.addLookup("ligatures", "gsub_ligature", (), (("liga", (("dflt", ("dflt")), ("latn", ("dflt")))), )) font.addLookupSubtable("ligatures", "ligatures-subtable") @@ -206,7 +206,6 @@ def generateFont(*, black=False, bold=False, semibold=False, light=False, extral font.macstyle = 2 font.os2_stylemap = 1 font.italicangle = -15 - for character in characters: charactersByCodepoint[character["codepoint"]] = character image, kw = generateImage(character) From d447d653c016676a94d18831615fd840a9b81e43 Mon Sep 17 00:00:00 2001 From: Nekosha <79341606+Nekosha@users.noreply.github.com> Date: Sat, 23 Mar 2024 20:19:25 +0700 Subject: [PATCH 11/11] make base a dotless i --- src/characters.json | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/characters.json b/src/characters.json index 1c73ab1..ab98d93 100644 --- a/src/characters.json +++ b/src/characters.json @@ -18332,9 +18332,18 @@ "codepoint": 7881, "name": "latin_small_letter_i_with_hook_above", "character": "ỉ", - "reference": 105, - "diacritic": "hook_above", - "diacriticSpace": 1 + "pixels": [ + [0, 1, 1, 0, 0], + [0, 0, 0, 1, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 1, 1, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 1, 1] + ], + "leftMargin": -0.5 }, { "codepoint": 7882,