feat: M3-M7 全模块落地 + 集成接线
- M3 认证/权限/审计/限流 + 全部 REST 接口 - M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制) - M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配) - M6 WebSocket 实时同步中心 - M7 xlsx 导出 + 赛事包 zip + 备份 - 规则包 YAML 导入导出(差异预览) - 字体 vendor 子集化(4 套 x2 字重) - 集成:realtime/export/rules 接入 main+httpapi;backup 子命令 - 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
This commit is contained in:
1 parent
d0e3b93e76
commit
bc8b1ee6c0
145 files changed
+25159
-321
No files matched your search
+81
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""把子集字体内部的 name 表 / OS2 字重统一成 CSS 期望的规范值。
|
||||
|
||||
为什么需要:思源黑体的老版本 OTF 把每个字重写成独立族名
|
||||
(`Source Han Sans CN Regular` / `Source Han Sans CN Bold`),
|
||||
MiSans 的 usWeightClass 是 330/630 这类非标准值。
|
||||
@font-face 的 `font-family` 描述符虽然能屏蔽内部族名,但保持一致更省心,
|
||||
也避免字体被单独安装/引用时族名对不上。
|
||||
|
||||
用法(由 subset-fonts.sh 调用):
|
||||
python3 vendor/fonts/tools/normalize-names.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from fontTools.ttLib import TTFont
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
OUT_DIR = HERE.parent
|
||||
CONF = HERE / "fonts.conf"
|
||||
|
||||
WEIGHTS = (("regular", "Regular", 400), ("bold", "Bold", 700))
|
||||
STALE_NAME_IDS = (1, 2, 3, 4, 6, 16, 17, 21, 22)
|
||||
PLATFORMS = ((3, 1, 0x409), (1, 0, 0)) # Windows / Mac,英文
|
||||
|
||||
|
||||
def set_name(name, name_id: int, value: str) -> None:
|
||||
for platform_id, plat_enc_id, lang_id in PLATFORMS:
|
||||
name.setName(value, name_id, platform_id, plat_enc_id, lang_id)
|
||||
|
||||
|
||||
def normalize(path: Path, family: str, style: str, weight: int) -> None:
|
||||
font = TTFont(path)
|
||||
name = font["name"]
|
||||
for record in list(name.names):
|
||||
if record.nameID in STALE_NAME_IDS:
|
||||
name.removeNames(record.nameID, record.platformID, record.platEncID, record.langID)
|
||||
|
||||
full_name = family if style == "Regular" else f"{family} {style}"
|
||||
set_name(name, 1, family) # family
|
||||
set_name(name, 2, style) # subfamily
|
||||
set_name(name, 3, f"{full_name}:subset") # unique id
|
||||
set_name(name, 4, full_name) # full name
|
||||
set_name(name, 6, full_name.replace(" ", "")) # postscript name
|
||||
set_name(name, 16, family) # typographic family
|
||||
set_name(name, 17, style) # typographic subfamily
|
||||
|
||||
os2 = font["OS/2"]
|
||||
os2.usWeightClass = weight
|
||||
if weight >= 700:
|
||||
os2.fsSelection = (os2.fsSelection & ~0x40) | 0x20 # BOLD
|
||||
font["head"].macStyle |= 0x01
|
||||
else:
|
||||
os2.fsSelection = (os2.fsSelection & ~0x20) | 0x40 # REGULAR
|
||||
font["head"].macStyle &= ~0x01
|
||||
|
||||
font.flavor = "woff2"
|
||||
font.save(path)
|
||||
font.close()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
for line in CONF.read_text(encoding="utf-8").splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
fid, _, family = [p.strip() for p in line.split("|")][:3]
|
||||
for weight_name, style, weight_class in WEIGHTS:
|
||||
path = OUT_DIR / f"{fid}-{weight_name}.woff2"
|
||||
if not path.is_file():
|
||||
print(f"缺少产物: {path}", file=sys.stderr)
|
||||
return 1
|
||||
normalize(path, family, style, weight_class)
|
||||
print(f" {path.name:32s} -> {family} / {style} ({weight_class})")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user