diff --git a/README.md b/README.md
index ea12ca3..52032aa 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ This project aims to be 100% faithful to the original Minecraft font by providin
1. Clone this repo
2. Run `uv run src/minecraft_seven/__init__.py`
3. Open [Pixel Font Converter](https://yal.cc/r/20/pixelfont/)
-4. Click `Menu` in the top right and select `Batch process`
+4. Click `Menu` on the upper left and select `Batch process`
5. Navigate to the `out` folder in this repo and select both the `png` and `json` file. (by holding Ctrl)
6. Install the ttf in the downloaded zip!
diff --git a/resources/1.21.toml b/resources/1.21.toml
index 1d87480..50d651f 100644
--- a/resources/1.21.toml
+++ b/resources/1.21.toml
@@ -1,7 +1,4 @@
-[tileset]
-tile_width = 9
-tile_height = 12
-tile_baseline = 10
+[output]
tileset_width = 21717
[providers."minecraft:font/ascii.png"]
diff --git a/src/minecraft_seven/__init__.py b/src/minecraft_seven/__init__.py
index 9db34bb..b8479b0 100644
--- a/src/minecraft_seven/__init__.py
+++ b/src/minecraft_seven/__init__.py
@@ -2,9 +2,11 @@
import os
from zipfile import ZipFile
from xdialog import open_file
-from minecraft_seven.builder import build_as_pixel_font_converter_batch
+from minecraft_seven.builder import build_font_assets
import json
+from minecraft_seven.pixel_font_exporter import export_to_pixel_font_converter_batch
+
MINECRAFT_VERSION = "1.21"
@@ -36,11 +38,14 @@ def check_minecraft_version(jar_path: str):
def main() -> None:
+ print("Getting jar file...")
jar_path = get_jar_path()
check_minecraft_version(jar_path)
- build_as_pixel_font_converter_batch(jar_path, MINECRAFT_VERSION)
- return
+ tileset, glyphs, dimensions = build_font_assets(jar_path, MINECRAFT_VERSION)
+
+ print("Exporting...")
+ export_to_pixel_font_converter_batch(tileset, glyphs, dimensions)
if __name__ == "__main__":
diff --git a/src/minecraft_seven/builder.py b/src/minecraft_seven/builder.py
index 3c82425..a4b9f97 100644
--- a/src/minecraft_seven/builder.py
+++ b/src/minecraft_seven/builder.py
@@ -5,6 +5,9 @@
from PIL import Image, ImageDraw
+type MinecraftClientJar = ZipFile
+
+
class Provider:
id: str
file: bytes
@@ -14,39 +17,74 @@ class Provider:
chars: list[str]
-def get_assets(jar_path: str, tile_data: dict) -> (list[Provider], int):
+class OutputDimensions:
+ tile_width: int
+ tile_height: int
+ tile_baseline: int
+ space_width: int
+ tileset_width: int
+
+
+def get_space_width(jar: MinecraftClientJar):
+ space_data: dict = json.loads(jar.read("assets/minecraft/font/include/space.json"))
+ return space_data["providers"][0]["advances"][" "]
+
+
+def get_font_data(jar: MinecraftClientJar):
+ return json.loads(jar.read("assets/minecraft/font/include/default.json"))
+
+
+def get_assets(
+ jar_path: str, dimensions: dict
+) -> tuple[list[Provider], OutputDimensions]:
+ out = OutputDimensions()
+ out.tileset_width = dimensions["output"]["tileset_width"]
+
with ZipFile(jar_path, "r") as jar:
- default_data: dict = json.loads(
- jar.read("assets/minecraft/font/include/default.json")
- )
- space_data: dict = json.loads(
- jar.read("assets/minecraft/font/include/space.json")
- )
- space_width = space_data["providers"][0]["advances"][" "]
- providers: list[dict] = default_data["providers"]
+ font_data = get_font_data(jar)
+ providers: list[dict] = font_data["providers"]
new_providers: list[Provider] = []
+ out.tile_width = 0
+ out.tile_height = 0
+ out.tile_baseline = 0
+
for provider in providers:
- new_provider: Provider = Provider()
- texture_id: str = provider["file"]
- new_provider.id = texture_id
- texture_name = texture_id.replace(
- "minecraft:", "assets/minecraft/textures/"
+ provider_dimensions = dimensions["providers"][provider["file"]]
+ new_provider = map_provider_json_to_class(
+ jar, provider, provider_dimensions
)
- new_provider.file = jar.read(texture_name)
-
- provider_tile_data = tile_data["providers"][texture_id]
- new_provider.width = provider_tile_data["width"]
- new_provider.height = provider_tile_data["height"]
- new_provider.chars = provider["chars"]
- new_provider.baseline = provider["ascent"]
+ if new_provider.width > out.tile_width:
+ out.tile_width = new_provider.width
+ if new_provider.height > out.tile_height:
+ out.tile_height = new_provider.height
+ out.tile_baseline = new_provider.baseline
new_providers.append(new_provider)
- return new_providers, space_width
+ out.space_width = get_space_width(jar)
+
+ return new_providers, out
-def load_tile_data(mc_version: str) -> dict:
+def map_provider_json_to_class(jar: MinecraftClientJar, provider, provider_dimensions):
+ new_provider: Provider = Provider()
+
+ texture_id: str = provider["file"]
+ new_provider.id = texture_id
+
+ texture_name = texture_id.replace("minecraft:", "assets/minecraft/textures/")
+ new_provider.file = jar.read(texture_name)
+
+ new_provider.chars = provider["chars"]
+ new_provider.baseline = provider["ascent"]
+ new_provider.width = provider_dimensions["width"]
+ new_provider.height = provider_dimensions["height"]
+
+ return new_provider
+
+
+def load_dimensions(mc_version: str) -> dict:
filename = "resources/" + mc_version + ".toml"
with open(filename, "r") as file:
return tomllib.loads(file.read())
@@ -60,70 +98,57 @@ def create_space_tile(width: int, height: int, space_width: int) -> Image:
def build_tileset(
- tileset_data: dict, providers: list[Provider], space_width: int
-) -> (Image, str):
- tile_width = tileset_data["tile_width"]
- tile_height = tileset_data["tile_height"]
- tile_baseline = tileset_data["tile_baseline"]
- tileset_width = tileset_data["tileset_width"]
-
- tileset = Image.new("RGBA", (tileset_width, tile_height), color=(255, 0, 0, 0))
+ providers: list[Provider], out: OutputDimensions
+) -> tuple[Image, str]:
+ tileset = Image.new(
+ "RGBA", (out.tileset_width, out.tile_height), color=(255, 0, 0, 0)
+ )
glyphs: str = ""
tileset_x = 0
for provider in providers:
- char_height = provider.height
- char_width = provider.width
- char_baseline = provider.baseline
- tile_height_offset = tile_baseline - char_baseline
+ tile_height_offset = out.tile_baseline - provider.baseline
font_img = Image.open(io.BytesIO(provider.file))
font_x = font_y = 0
for chars in provider.chars: # "abcdefghij"
for char in chars: # "a"
- if char != "\x00":
- print(char)
- if char != " ":
- char_img = font_img.crop(
- (font_x, font_y, font_x + char_width, font_y + char_height)
+ if char == "\x00":
+ break
+
+ if char == " ":
+ char_img = create_space_tile(
+ provider.width, provider.height, out.space_width
+ )
+ else:
+ char_img = font_img.crop(
+ (
+ font_x,
+ font_y,
+ font_x + provider.width,
+ font_y + provider.height,
)
- else:
- char_img = create_space_tile(
- char_width, char_height, space_width
- )
- tileset.paste(char_img, (tileset_x, tile_height_offset))
- glyphs += char
+ )
+ tileset.paste(char_img, (tileset_x, tile_height_offset))
+ glyphs += char
+ tileset_x += out.tile_width
+ font_x += provider.width
- tileset_x += tile_width
- font_x += char_width
+ # Start at 0 at next row
font_x = 0
- font_y += char_height
+ font_y += provider.height
return tileset, glyphs
-def convert_to_pixel_font_converter_batch(
- tileset: Image, glyphs: str, tileset_data: dict
-):
- with open("resources/pixel_font_converter_settings.json") as settings_file:
- settings = json.load(settings_file)
-
- settings["glyph-width"] = tileset_data["tile_width"]
- settings["glyph-height"] = tileset_data["tile_height"]
- settings["glyph-baseline"] = tileset_data["tile_baseline"]
-
- settings["in-glyphs"] = [glyphs]
+def build_font_assets(
+ jar_path: str, mc_version: str
+) -> tuple[Image, str, OutputDimensions]:
+ print("Getting assets...")
+ dimensions = load_dimensions(mc_version)
+ providers, output_dimensions = get_assets(jar_path, dimensions)
- with open("out/Minecraft Seven.json", "w") as settings_output_file:
- json.dump(settings, settings_output_file)
+ print("Building tileset...")
+ tileset, glyphs = build_tileset(providers, output_dimensions)
- tileset.save("out/Minecraft Seven.png")
-
-
-def build_as_pixel_font_converter_batch(jar_path: str, mc_version: str):
- tile_data = load_tile_data(mc_version)
- providers, space_width = get_assets(jar_path, tile_data)
- for provider in providers:
- print(provider.id)
- tileset, glyphs = build_tileset(tile_data["tileset"], providers, space_width)
- convert_to_pixel_font_converter_batch(tileset, glyphs, tile_data["tileset"])
+ return tileset, glyphs, output_dimensions
diff --git a/src/minecraft_seven/pixel_font_exporter.py b/src/minecraft_seven/pixel_font_exporter.py
new file mode 100644
index 0000000..3afe819
--- /dev/null
+++ b/src/minecraft_seven/pixel_font_exporter.py
@@ -0,0 +1,47 @@
+import json
+
+from PIL import Image
+
+from minecraft_seven.builder import OutputDimensions
+
+
+def export_to_pixel_font_converter_batch(
+ tileset: Image, glyphs: str, out: OutputDimensions
+):
+ with open("resources/pixel_font_converter_settings.json") as settings_file:
+ settings = json.load(settings_file)
+
+ settings["glyph-width"] = out.tile_width
+ settings["glyph-height"] = out.tile_height
+ settings["glyph-baseline"] = out.tile_baseline
+
+ settings["in-glyphs"] = [glyphs]
+
+ with open("out/Minecraft Seven.json", "w") as settings_output_file:
+ json.dump(settings, settings_output_file)
+
+ tileset.save("out/Minecraft Seven.png")
+
+ show_done_msg()
+
+
+def show_done_msg():
+ print(f"""
+Done!
+
+1. Go to {link("https://yal.cc/r/20/pixelfont/", "[🔗 Pixel Font Converter]")}
+2. Click `Menu` on the upper left and select `Batch process`
+3. Navigate to the `out` folder in this repo and select both the `png` and `json` file. (by holding `Ctrl`)
+4. Install the ttf in the downloaded zip!
+ """)
+
+
+def link(uri: str, label: str = None):
+ if label is None:
+ label = uri
+ parameters = ""
+
+ # OSC 8 ; params ; URI ST OSC 8 ;; ST
+ escape_mask = "\033]8;{};{}\033\\{}\033]8;;\033\\"
+
+ return escape_mask.format(parameters, uri, label)