Path: blob/master/tools/lib/python/kdoc/latex_fonts.py
122941 views
#!/usr/bin/env python31# SPDX-License-Identifier: GPL-2.0-only2# Copyright (C) Akira Yokosawa, 20243#4# Ported to Python by (c) Mauro Carvalho Chehab, 202556"""7Detect problematic Noto CJK variable fonts8==========================================910For ``make pdfdocs``, reports of build errors of translations.pdf started11arriving early 2024 [1]_ [2]_. It turned out that Fedora and openSUSE12tumbleweed have started deploying variable-font [3]_ format of "Noto CJK"13fonts [4]_ [5]_. For PDF, a LaTeX package named xeCJK is used for CJK14(Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which15does not (and likely never will) understand variable fonts for historical16reasons.1718The build error happens even when both of variable- and non-variable-format19fonts are found on the build system. To make matters worse, Fedora enlists20variable "Noto CJK" fonts in the requirements of langpacks-ja, -ko, -zh_CN,21-zh_TW, etc. Hence developers who have interest in CJK pages are more22likely to encounter the build errors.2324This script is invoked from the error path of "make pdfdocs" and emits25suggestions if variable-font files of "Noto CJK" fonts are in the list of26fonts accessible from XeTeX.2728.. [1] https://lore.kernel.org/r/[email protected]/29.. [2] https://lore.kernel.org/r/[email protected]/30.. [3] https://en.wikipedia.org/wiki/Variable_font31.. [4] https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts32.. [5] https://build.opensuse.org/request/show/11572173334Workarounds for building translations.pdf35-----------------------------------------3637* Denylist "variable font" Noto CJK fonts.3839- Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with40tweaks if necessary. Remove leading "".4142- Path of fontconfig/fonts.conf can be overridden by setting an env43variable FONTS_CONF_DENY_VF.4445* Template::4647<?xml version="1.0"?>48<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">49<fontconfig>50<!--51Ignore variable-font glob (not to break xetex)52-->53<selectfont>54<rejectfont>55<!--56for Fedora57-->58<glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob>59<!--60for openSUSE tumbleweed61-->62<glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob>63</rejectfont>64</selectfont>65</fontconfig>6667The denylisting is activated for "make pdfdocs".6869* For skipping CJK pages in PDF7071- Uninstall texlive-xecjk.72Denylisting is not needed in this case.7374* For printing CJK pages in PDF7576- Need non-variable "Noto CJK" fonts.7778* Fedora7980- google-noto-sans-cjk-fonts81- google-noto-serif-cjk-fonts8283* openSUSE tumbleweed8485- Non-variable "Noto CJK" fonts are not available as distro packages86as of April, 2024. Fetch a set of font files from upstream Noto87CJK Font released at:8889https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc9091and at:9293https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc9495then uncompress and deploy them.96- Remember to update fontconfig cache by running fc-cache.9798.. caution::99Uninstalling "variable font" packages can be dangerous.100They might be depended upon by other packages important for your work.101Denylisting should be less invasive, as it is effective only while102XeLaTeX runs in "make pdfdocs".103"""104105import os106import re107import subprocess108import textwrap109import sys110111class LatexFontChecker:112"""113Detect problems with CJK variable fonts that affect PDF builds for114translations.115"""116117def __init__(self, deny_vf=None):118if not deny_vf:119deny_vf = os.environ.get('FONTS_CONF_DENY_VF', "~/deny-vf")120121self.environ = os.environ.copy()122self.environ['XDG_CONFIG_HOME'] = os.path.expanduser(deny_vf)123124self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK")125126def description(self):127"""128Returns module description.129"""130return __doc__131132def get_noto_cjk_vf_fonts(self):133"""134Get Noto CJK fonts.135"""136137cjk_fonts = set()138cmd = ["fc-list", ":", "file", "family", "variable"]139try:140result = subprocess.run(cmd,stdout=subprocess.PIPE,141stderr=subprocess.PIPE,142universal_newlines=True,143env=self.environ,144check=True)145146except subprocess.CalledProcessError as exc:147sys.exit(f"Error running fc-list: {repr(exc)}")148149for line in result.stdout.splitlines():150if 'variable=True' not in line:151continue152153match = self.re_cjk.search(line)154if match:155cjk_fonts.add(match.group(1))156157return sorted(cjk_fonts)158159def check(self):160"""161Check for problems with CJK fonts.162"""163164fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ")165if not fonts:166return None167168rel_file = os.path.relpath(__file__, os.getcwd())169170msg = "=" * 77 + "\n"171msg += 'XeTeX is confused by "variable font" files listed below:\n'172msg += fonts + "\n"173msg += textwrap.dedent(f"""174For CJK pages in PDF, they need to be hidden from XeTeX by denylisting.175Or, CJK pages can be skipped by uninstalling texlive-xecjk.176177For more info on denylisting, other options, and variable font, run:178179tools/docs/check-variable-fonts.py -h180""")181msg += "=" * 77182183return msg184185186