"""번들 폰트(NanumSquare) 로딩. `font/` 디렉토리의 TTF를 QFontDatabase에 등록해 OS 설치 없이도 사용. PyInstaller frozen(_MEIPASS) / 개발 실행(프로젝트 루트) 양쪽 경로를 지원하며, 등록 실패 시 QSS 폰트 체인이 "Malgun Gothic"으로 자연 폴백한다. """ from __future__ import annotations import os import sys from PyQt5.QtGui import QFontDatabase, QFont # 로드할 폰트 파일 — TTF 우선(Windows Qt에서 OTF보다 렌더 안정적). # L/R/B/EB 4단계 굵기 + _ac(라틴·숫자 보정) 변형을 함께 등록. _FONT_FILES = [ 'NanumSquareL.ttf', 'NanumSquareR.ttf', 'NanumSquareB.ttf', 'NanumSquareEB.ttf', 'NanumSquare_acR.ttf', 'NanumSquare_acB.ttf', ] def _font_dir() -> str: """번들 font/ 디렉토리 절대 경로.""" if getattr(sys, 'frozen', False): base = getattr(sys, '_MEIPASS', None) or os.path.dirname(sys.executable) else: base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) return os.path.join(base, 'font') def load_bundled_fonts() -> list: """번들 폰트를 등록하고, 등록된 family 이름 목록을 반환.""" families: list = [] fdir = _font_dir() if not os.path.isdir(fdir): return families for name in _FONT_FILES: path = os.path.join(fdir, name) if not os.path.exists(path): continue fid = QFontDatabase.addApplicationFont(path) if fid == -1: continue for fam in QFontDatabase.applicationFontFamilies(fid): if fam not in families: families.append(fam) return families def _pick_primary(families: list) -> str: """등록된 family 중 기본 본문용(Regular 굵기) family 선택.""" if 'NanumSquare' in families: return 'NanumSquare' for fam in families: low = fam.lower() if 'nanumsquare' in low and 'light' not in low and 'extra' not in low: return fam return 'Malgun Gothic' def apply_app_font(app, point_size: int = 9) -> str: """앱 전역 기본 폰트를 NanumSquare로 설정. Returns: 실제 적용된 primary family 이름 (폴백 시 'Malgun Gothic'). """ families = load_bundled_fonts() primary = _pick_primary(families) font = QFont(primary, point_size) font.setStyleStrategy(QFont.PreferAntialias) app.setFont(font) return primary if __name__ == '__main__': from PyQt5.QtWidgets import QApplication _app = QApplication(sys.argv) fams = load_bundled_fonts() print('font dir:', _font_dir()) print('registered families:', fams) print('picked primary:', _pick_primary(fams))