add fonts

This commit is contained in:
chenxiangtong
2026-03-26 18:07:53 +08:00
parent a05ce6e07e
commit 6e3dc7807b
2 changed files with 43 additions and 3 deletions

View File

@@ -8,6 +8,10 @@ _regular_path: str | None = None
_bold_path: str | None = None
_initialized: bool = False
# 项目内置字体目录src/render/pillow/fonts/
# 支持 .ttf / .ttc / .otf文件名含 "bold" 的优先用作粗体
_LOCAL_FONTS_DIR = Path(__file__).parent / "fonts"
_CANDIDATES: dict[str, dict[bool, list[str]]] = {
"win32": {
False: [
@@ -49,18 +53,50 @@ _CANDIDATES: dict[str, dict[bool, list[str]]] = {
}
def _scan_local_fonts() -> tuple[str | None, str | None]:
"""
扫描 src/render/pillow/fonts/ 目录,返回 (regular_path, bold_path)。
规则:
- 文件名包含 "bold"(不区分大小写)→ 优先作为粗体
- 其余文件 → 作为常规字体
- 若只找到一个文件,常规和粗体均使用它
"""
if not _LOCAL_FONTS_DIR.is_dir():
return None, None
exts = {".ttf", ".ttc", ".otf"}
all_fonts = [p for p in _LOCAL_FONTS_DIR.iterdir() if p.suffix.lower() in exts]
if not all_fonts:
return None, None
bold_fonts = [p for p in all_fonts if "bold" in p.stem.lower()]
regular_fonts = [p for p in all_fonts if p not in bold_fonts]
regular = str(regular_fonts[0]) if regular_fonts else str(all_fonts[0])
bold = str(bold_fonts[0]) if bold_fonts else regular
return regular, bold
def _init() -> None:
global _regular_path, _bold_path, _initialized
if _initialized:
return
# 1. 优先使用项目内 fonts/ 目录
local_regular, local_bold = _scan_local_fonts()
if local_regular:
_regular_path = local_regular
_bold_path = local_bold
_initialized = True
return
# 2. 回退到系统字体
platform = sys.platform if sys.platform in _CANDIDATES else "linux"
def _find(bold: bool) -> str | None:
for p in _CANDIDATES[platform][bold]:
if Path(p).exists():
return p
# Cross-platform fallback: try all platforms' regular fonts
for plat_cands in _CANDIDATES.values():
for p in plat_cands[False]:
if Path(p).exists():
@@ -72,7 +108,9 @@ def _init() -> None:
_initialized = True
def get_font(size: int, bold: bool = False) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
def get_font(
size: int, bold: bool = False
) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
"""Return a CJK-compatible font at the requested size."""
_init()
key = (bold, size)
@@ -90,7 +128,9 @@ def get_font(size: int, bold: bool = False) -> ImageFont.FreeTypeFont | ImageFon
# Ultimate fallback: PIL built-in bitmap font
try:
fb: ImageFont.FreeTypeFont | ImageFont.ImageFont = ImageFont.load_default(size=size)
fb: ImageFont.FreeTypeFont | ImageFont.ImageFont = ImageFont.load_default(
size=size
)
except TypeError:
fb = ImageFont.load_default()
_cache[key] = fb

View File