"""Регистрация TTF с кириллицей для reportlab (Linux / macOS / Windows).""" from __future__ import annotations import os from pathlib import Path from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont _FONT_REGISTERED = False _FONT_BOLD_REGISTERED = False _PROJECT_ROOT = Path(__file__).resolve().parents[2] def _windows_fonts_dir() -> Path: windir = os.environ.get("WINDIR", r"C:\Windows") return Path(windir) / "Fonts" def _cyrillic_font_candidates(*, bold: bool = False) -> list[Path]: bundled = ( _PROJECT_ROOT / "vendor" / "fonts" / ("DejaVuSans-Bold.ttf" if bold else "DejaVuSans.ttf") ) candidates: list[Path] = [bundled] if os.name == "nt": win = _windows_fonts_dir() if bold: candidates.extend( [ win / "arialbd.ttf", win / "segoeuib.ttf", win / "calibrib.ttf", win / "timesbd.ttf", ] ) else: candidates.extend( [ win / "arial.ttf", win / "segoeui.ttf", win / "calibri.ttf", win / "times.ttf", ] ) if bold: candidates.extend( [ Path("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"), Path("/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf"), Path("/System/Library/Fonts/Supplemental/Arial Bold.ttf"), Path("/Library/Fonts/Arial Bold.ttf"), ] ) else: candidates.extend( [ Path("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"), Path("/usr/share/fonts/dejavu/DejaVuSans.ttf"), Path("/System/Library/Fonts/Supplemental/Arial Unicode.ttf"), Path("/Library/Fonts/Arial Unicode.ttf"), Path("/System/Library/Fonts/Supplemental/Arial.ttf"), ] ) seen: set[str] = set() unique: list[Path] = [] for path in candidates: key = str(path).lower() if key in seen: continue seen.add(key) unique.append(path) return unique def register_cyrillic_font() -> str: """Возвращает имя зарегистрированного шрифта reportlab или Helvetica (без кириллицы).""" global _FONT_REGISTERED if _FONT_REGISTERED: return "WespCyr" for path in _cyrillic_font_candidates(bold=False): if not path.is_file(): continue try: pdfmetrics.registerFont(TTFont("WespCyr", str(path))) _FONT_REGISTERED = True return "WespCyr" except Exception: continue return "Helvetica" def register_cyrillic_font_bold() -> str: global _FONT_BOLD_REGISTERED if _FONT_BOLD_REGISTERED: return "WespCyrBold" for path in _cyrillic_font_candidates(bold=True): if not path.is_file(): continue try: pdfmetrics.registerFont(TTFont("WespCyrBold", str(path))) _FONT_BOLD_REGISTERED = True return "WespCyrBold" except Exception: continue return register_cyrillic_font()