三特性: 字体分层(gen_font.py --charset + meow_font_reload_tier + font.load_full + 尺寸标记) + 全屏机制/状态栏收合(meow_ui_sys/input) + 通知#6 TF转储(CSV+10MB+开机清板载+内存表)
This commit is contained in:
1 parent
0b4d1d3215
commit
a2673d5922
18 files changed
+819
-80
No files matched your search
+93
-6
@@ -44,8 +44,11 @@ idx 二进制布局(little-endian, version=2):
|
||||
+15 u8 dy
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import unicodedata
|
||||
import zlib
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
@@ -96,32 +99,80 @@ def pack_plane_depth(plane_l8, width, height, depth):
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 字符集
|
||||
# 字符集(字体档位:common / gbk / full)
|
||||
# 口径见 docs/MEOWOS_SPEC_REF.md §5.2「字体档位/大字库」与 §5.7.8:
|
||||
# common ≈ 4k 码位(ASCII + GB2312 常用 + 标点 + --extra) = 现状;
|
||||
# gbk ≈ 20k+(再并入 CJK 统一表意 U+4E00-9FFF + CJK 符号/全角,含常用简繁/生僻);
|
||||
# full ≈ 全 Unicode 可渲染区间(gbk + CJK 扩展 A/B-F + 拉丁/希腊/西里尔 + 通用标点,可选)。
|
||||
# 每档在产物 font.json 写入 charset + glyph_count(见 write_font_json)。
|
||||
# --------------------------------------------------------------------------
|
||||
def build_charset(extra=""):
|
||||
CHARSET_TIERS = ("common", "gbk", "full")
|
||||
CHARSET_ALIAS = {"0": "common", "common": "common", "1": "gbk", "gbk": "gbk",
|
||||
"2": "full", "full": "full"}
|
||||
|
||||
|
||||
def build_charset(tier="common", extra=""):
|
||||
if tier not in CHARSET_TIERS:
|
||||
tier = "common"
|
||||
cps = []
|
||||
def add(cp):
|
||||
if cp not in cps:
|
||||
if 0 <= cp <= 0x10FFFF and cp not in cps:
|
||||
cps.append(cp)
|
||||
# ASCII 可打印字符
|
||||
for c in range(0x20, 0x7F):
|
||||
add(c)
|
||||
# GB2312 一/二级常用简体(B0-D7 + D8 常用二级首段)
|
||||
for hi in range(0xB0, 0xD8):
|
||||
for lo in range(0xA1, 0xFF):
|
||||
try:
|
||||
add(ord(bytes([hi, lo]).decode("gb2312")))
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
for hi in range(0xA1, 0xA4):
|
||||
# GB2312 符号/全角(A1-A4)
|
||||
for hi in range(0xA1, 0xA5):
|
||||
for lo in range(0xA1, 0xFF):
|
||||
try:
|
||||
add(ord(bytes([hi, lo]).decode("gb2312")))
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
if tier in ("gbk", "full"):
|
||||
# CJK 统一表意(含常用简繁/生僻):U+4E00-9FFF ≈ 2万+
|
||||
for cp in range(0x4E00, 0xA000):
|
||||
add(cp)
|
||||
# CJK 符号与标点 + 全角形式(补齐 common 未含的)
|
||||
for cp in range(0x3000, 0x3040):
|
||||
add(cp)
|
||||
for cp in range(0xFF00, 0xFFF0):
|
||||
add(cp)
|
||||
if tier == "full":
|
||||
# 拉丁补充 / 希腊 / 西里尔 等常用非 CJK(Latin-1 起已覆盖 AI 常见重音)
|
||||
for cp in range(0xA0, 0x0530):
|
||||
add(cp)
|
||||
# CJK 扩展 A + 兼容表意
|
||||
for cp in range(0x3400, 0x4DC0):
|
||||
add(cp)
|
||||
for cp in range(0xF900, 0xFB00):
|
||||
add(cp)
|
||||
# 通用标点 / 货币等(— … “ ” 等已在 gbk;此处补全)
|
||||
for cp in range(0x2000, 0x2070):
|
||||
add(cp)
|
||||
for cp in range(0x20A0, 0x20D0):
|
||||
add(cp)
|
||||
# CJK 扩展 B-F(补充平面)
|
||||
for cp in range(0x20000, 0x2EBF0):
|
||||
add(cp)
|
||||
for cp in range(0x30000, 0x31350):
|
||||
add(cp)
|
||||
for ch in extra:
|
||||
add(ord(ch))
|
||||
return sorted(cps)
|
||||
|
||||
|
||||
def charset_glyph_count(cps):
|
||||
"""glyph_count = 字符集码位数(信息用,落 font.json)。"""
|
||||
return len(cps)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 逐字形渲染
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -227,6 +278,33 @@ def write_idx(path, bit_depth, faces, glyph_tabs):
|
||||
return len(header) + len(body)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# font.json(元数据 + 完整性校验;schema 见 docs/MEOWOS_SPEC_REF.md §5.2)
|
||||
# --------------------------------------------------------------------------
|
||||
def write_font_json(out_dir, name, family, tier, glyph_count, sizes, bitdepth,
|
||||
png_path, idx_path):
|
||||
def sha256(path):
|
||||
h = hashlib.sha256()
|
||||
with open(path, "rb") as f:
|
||||
for blk in iter(lambda: f.read(1 << 16), b""):
|
||||
h.update(blk)
|
||||
return h.hexdigest()
|
||||
meta = {
|
||||
"family": family or name, # 同目录名(信息用;扫描端以目录名为 family)
|
||||
"name": name, # 下拉显示名(缺则回退目录名)
|
||||
"glyph_count": glyph_count, # 信息用
|
||||
"charset": tier, # common|gbk|full(档位;驱动按需加载)
|
||||
"size_list": sizes, # 原生面字号
|
||||
"bit_depth": bitdepth, # 4|8
|
||||
"sha256_png": sha256(png_path), # font.png 校验(扫描端仅 WARN)
|
||||
"sha256_idx": sha256(idx_path), # font.idx 校验(扫描端仅 WARN)
|
||||
}
|
||||
jpath = os.path.join(out_dir, "font.json")
|
||||
with open(jpath, "w", encoding="utf-8") as f:
|
||||
json.dump(meta, f, ensure_ascii=False, indent=2)
|
||||
return jpath
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 主流程
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -236,14 +314,18 @@ def main():
|
||||
ap.add_argument("--sizes", default="28,20")
|
||||
ap.add_argument("--out", required=True)
|
||||
ap.add_argument("--name", default="font")
|
||||
ap.add_argument("--family", default="", help="font.json family(缺省 = --name;信息用)")
|
||||
ap.add_argument("--charset", default="common", choices=CHARSET_TIERS,
|
||||
help="字体档位:common≈4k / gbk≈20k+ / full(可选,默认不推)")
|
||||
ap.add_argument("--bitdepth", type=int, default=4, choices=(4, 8))
|
||||
ap.add_argument("--extra", default="")
|
||||
args = ap.parse_args()
|
||||
|
||||
os.makedirs(args.out, exist_ok=True)
|
||||
sizes = [int(s) for s in args.sizes.split(",") if s.strip()]
|
||||
cps = build_charset(args.extra)
|
||||
print(f"字符集: {len(cps)} 码位")
|
||||
tier = CHARSET_ALIAS.get(args.charset, "common")
|
||||
cps = build_charset(tier, args.extra)
|
||||
print(f"字符集: {len(cps)} 码位 (charset={tier})")
|
||||
|
||||
all_planes = [] # (aw, ah, plane_l8 bytes, tab)
|
||||
max_w = 0
|
||||
@@ -311,10 +393,15 @@ def main():
|
||||
idx_path = os.path.join(args.out, f"{args.name}.idx")
|
||||
idx_size = write_idx(idx_path, args.bitdepth, face_meta, [p[3] for p in all_planes])
|
||||
|
||||
# ---- font.json(写入 charset + glyph_count + sha256,供扫描端标注档位/大小标记) ----
|
||||
jpath = write_font_json(args.out, args.name, args.family, tier, charset_glyph_count(cps),
|
||||
sizes, args.bitdepth, png_path, idx_path)
|
||||
|
||||
png_size = os.path.getsize(png_path)
|
||||
total = png_size + idx_size
|
||||
print(f"\nfont.png {png_size} B")
|
||||
print(f"font.idx {idx_size} B")
|
||||
print(f"font.json {os.path.getsize(jpath)} B (charset={tier}, glyph_count={len(cps)})")
|
||||
print(f"合计 {total} B = {total/1024:.1f} KiB = {total/1048576:.2f} MiB (预算 2MiB)")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user