14515ffdfSMauro Carvalho Chehab#!/usr/bin/env python3 24515ffdfSMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0-only 34515ffdfSMauro Carvalho Chehab# Copyright (C) Akira Yokosawa, 2024 44515ffdfSMauro Carvalho Chehab# 54515ffdfSMauro Carvalho Chehab# Ported to Python by (c) Mauro Carvalho Chehab, 2025 64515ffdfSMauro Carvalho Chehab 74515ffdfSMauro Carvalho Chehab""" 8*4d7f6319SMauro Carvalho ChehabDetect problematic Noto CJK variable fonts 9*4d7f6319SMauro Carvalho Chehab========================================== 104515ffdfSMauro Carvalho Chehab 11*4d7f6319SMauro Carvalho ChehabFor ``make pdfdocs``, reports of build errors of translations.pdf started 12*4d7f6319SMauro Carvalho Chehabarriving early 2024 [1]_ [2]_. It turned out that Fedora and openSUSE 13*4d7f6319SMauro Carvalho Chehabtumbleweed have started deploying variable-font [3]_ format of "Noto CJK" 14*4d7f6319SMauro Carvalho Chehabfonts [4]_ [5]_. For PDF, a LaTeX package named xeCJK is used for CJK 154515ffdfSMauro Carvalho Chehab(Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which 164515ffdfSMauro Carvalho Chehabdoes not (and likely never will) understand variable fonts for historical 174515ffdfSMauro Carvalho Chehabreasons. 184515ffdfSMauro Carvalho Chehab 194515ffdfSMauro Carvalho ChehabThe build error happens even when both of variable- and non-variable-format 204515ffdfSMauro Carvalho Chehabfonts are found on the build system. To make matters worse, Fedora enlists 214515ffdfSMauro Carvalho Chehabvariable "Noto CJK" fonts in the requirements of langpacks-ja, -ko, -zh_CN, 224515ffdfSMauro Carvalho Chehab-zh_TW, etc. Hence developers who have interest in CJK pages are more 234515ffdfSMauro Carvalho Chehablikely to encounter the build errors. 244515ffdfSMauro Carvalho Chehab 254515ffdfSMauro Carvalho ChehabThis script is invoked from the error path of "make pdfdocs" and emits 264515ffdfSMauro Carvalho Chehabsuggestions if variable-font files of "Noto CJK" fonts are in the list of 274515ffdfSMauro Carvalho Chehabfonts accessible from XeTeX. 284515ffdfSMauro Carvalho Chehab 29*4d7f6319SMauro Carvalho Chehab.. [1] https://lore.kernel.org/r/8734tqsrt7.fsf@meer.lwn.net/ 30*4d7f6319SMauro Carvalho Chehab.. [2] https://lore.kernel.org/r/1708585803.600323099@f111.i.mail.ru/ 31*4d7f6319SMauro Carvalho Chehab.. [3] https://en.wikipedia.org/wiki/Variable_font 32*4d7f6319SMauro Carvalho Chehab.. [4] https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts 33*4d7f6319SMauro Carvalho Chehab.. [5] https://build.opensuse.org/request/show/1157217 344515ffdfSMauro Carvalho Chehab 354515ffdfSMauro Carvalho ChehabWorkarounds for building translations.pdf 36*4d7f6319SMauro Carvalho Chehab----------------------------------------- 374515ffdfSMauro Carvalho Chehab 384515ffdfSMauro Carvalho Chehab* Denylist "variable font" Noto CJK fonts. 39*4d7f6319SMauro Carvalho Chehab 404515ffdfSMauro Carvalho Chehab - Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with 414515ffdfSMauro Carvalho Chehab tweaks if necessary. Remove leading "". 42*4d7f6319SMauro Carvalho Chehab 434515ffdfSMauro Carvalho Chehab - Path of fontconfig/fonts.conf can be overridden by setting an env 444515ffdfSMauro Carvalho Chehab variable FONTS_CONF_DENY_VF. 454515ffdfSMauro Carvalho Chehab 46*4d7f6319SMauro Carvalho Chehab * Template:: 47*4d7f6319SMauro Carvalho Chehab 484515ffdfSMauro Carvalho Chehab <?xml version="1.0"?> 494515ffdfSMauro Carvalho Chehab <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 504515ffdfSMauro Carvalho Chehab <fontconfig> 514515ffdfSMauro Carvalho Chehab <!-- 524515ffdfSMauro Carvalho Chehab Ignore variable-font glob (not to break xetex) 534515ffdfSMauro Carvalho Chehab --> 544515ffdfSMauro Carvalho Chehab <selectfont> 554515ffdfSMauro Carvalho Chehab <rejectfont> 564515ffdfSMauro Carvalho Chehab <!-- 574515ffdfSMauro Carvalho Chehab for Fedora 584515ffdfSMauro Carvalho Chehab --> 594515ffdfSMauro Carvalho Chehab <glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob> 604515ffdfSMauro Carvalho Chehab <!-- 614515ffdfSMauro Carvalho Chehab for openSUSE tumbleweed 624515ffdfSMauro Carvalho Chehab --> 634515ffdfSMauro Carvalho Chehab <glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob> 644515ffdfSMauro Carvalho Chehab </rejectfont> 654515ffdfSMauro Carvalho Chehab </selectfont> 664515ffdfSMauro Carvalho Chehab </fontconfig> 674515ffdfSMauro Carvalho Chehab 684515ffdfSMauro Carvalho Chehab The denylisting is activated for "make pdfdocs". 694515ffdfSMauro Carvalho Chehab 704515ffdfSMauro Carvalho Chehab* For skipping CJK pages in PDF 71*4d7f6319SMauro Carvalho Chehab 724515ffdfSMauro Carvalho Chehab - Uninstall texlive-xecjk. 734515ffdfSMauro Carvalho Chehab Denylisting is not needed in this case. 744515ffdfSMauro Carvalho Chehab 754515ffdfSMauro Carvalho Chehab* For printing CJK pages in PDF 76*4d7f6319SMauro Carvalho Chehab 774515ffdfSMauro Carvalho Chehab - Need non-variable "Noto CJK" fonts. 78*4d7f6319SMauro Carvalho Chehab 794515ffdfSMauro Carvalho Chehab * Fedora 80*4d7f6319SMauro Carvalho Chehab 814515ffdfSMauro Carvalho Chehab - google-noto-sans-cjk-fonts 824515ffdfSMauro Carvalho Chehab - google-noto-serif-cjk-fonts 83*4d7f6319SMauro Carvalho Chehab 844515ffdfSMauro Carvalho Chehab * openSUSE tumbleweed 85*4d7f6319SMauro Carvalho Chehab 864515ffdfSMauro Carvalho Chehab - Non-variable "Noto CJK" fonts are not available as distro packages 874515ffdfSMauro Carvalho Chehab as of April, 2024. Fetch a set of font files from upstream Noto 884515ffdfSMauro Carvalho Chehab CJK Font released at: 89*4d7f6319SMauro Carvalho Chehab 904515ffdfSMauro Carvalho Chehab https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc 91*4d7f6319SMauro Carvalho Chehab 924515ffdfSMauro Carvalho Chehab and at: 93*4d7f6319SMauro Carvalho Chehab 944515ffdfSMauro Carvalho Chehab https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc 95*4d7f6319SMauro Carvalho Chehab 96*4d7f6319SMauro Carvalho Chehab then uncompress and deploy them. 974515ffdfSMauro Carvalho Chehab - Remember to update fontconfig cache by running fc-cache. 984515ffdfSMauro Carvalho Chehab 99*4d7f6319SMauro Carvalho Chehab.. caution:: 1004515ffdfSMauro Carvalho Chehab Uninstalling "variable font" packages can be dangerous. 1014515ffdfSMauro Carvalho Chehab They might be depended upon by other packages important for your work. 1024515ffdfSMauro Carvalho Chehab Denylisting should be less invasive, as it is effective only while 1034515ffdfSMauro Carvalho Chehab XeLaTeX runs in "make pdfdocs". 1044515ffdfSMauro Carvalho Chehab""" 1054515ffdfSMauro Carvalho Chehab 1064515ffdfSMauro Carvalho Chehabimport os 1074515ffdfSMauro Carvalho Chehabimport re 1084515ffdfSMauro Carvalho Chehabimport subprocess 1094515ffdfSMauro Carvalho Chehabimport textwrap 1104515ffdfSMauro Carvalho Chehabimport sys 1114515ffdfSMauro Carvalho Chehab 1124515ffdfSMauro Carvalho Chehabclass LatexFontChecker: 1134515ffdfSMauro Carvalho Chehab """ 1144515ffdfSMauro Carvalho Chehab Detect problems with CJK variable fonts that affect PDF builds for 1154515ffdfSMauro Carvalho Chehab translations. 1164515ffdfSMauro Carvalho Chehab """ 1174515ffdfSMauro Carvalho Chehab 11892ea342fSMauro Carvalho Chehab def __init__(self, deny_vf=None): 11992ea342fSMauro Carvalho Chehab if not deny_vf: 1204515ffdfSMauro Carvalho Chehab deny_vf = os.environ.get('FONTS_CONF_DENY_VF', "~/deny-vf") 1214515ffdfSMauro Carvalho Chehab 1224515ffdfSMauro Carvalho Chehab self.environ = os.environ.copy() 1234515ffdfSMauro Carvalho Chehab self.environ['XDG_CONFIG_HOME'] = os.path.expanduser(deny_vf) 1244515ffdfSMauro Carvalho Chehab 1254515ffdfSMauro Carvalho Chehab self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK") 1264515ffdfSMauro Carvalho Chehab 12792ea342fSMauro Carvalho Chehab def description(self): 128*4d7f6319SMauro Carvalho Chehab """ 129*4d7f6319SMauro Carvalho Chehab Returns module description. 130*4d7f6319SMauro Carvalho Chehab """ 13192ea342fSMauro Carvalho Chehab return __doc__ 13292ea342fSMauro Carvalho Chehab 1334515ffdfSMauro Carvalho Chehab def get_noto_cjk_vf_fonts(self): 134*4d7f6319SMauro Carvalho Chehab """ 135*4d7f6319SMauro Carvalho Chehab Get Noto CJK fonts. 136*4d7f6319SMauro Carvalho Chehab """ 1374515ffdfSMauro Carvalho Chehab 1384515ffdfSMauro Carvalho Chehab cjk_fonts = set() 1394515ffdfSMauro Carvalho Chehab cmd = ["fc-list", ":", "file", "family", "variable"] 1404515ffdfSMauro Carvalho Chehab try: 1414515ffdfSMauro Carvalho Chehab result = subprocess.run(cmd,stdout=subprocess.PIPE, 1424515ffdfSMauro Carvalho Chehab stderr=subprocess.PIPE, 1434515ffdfSMauro Carvalho Chehab universal_newlines=True, 1444515ffdfSMauro Carvalho Chehab env=self.environ, 1454515ffdfSMauro Carvalho Chehab check=True) 1464515ffdfSMauro Carvalho Chehab 1474515ffdfSMauro Carvalho Chehab except subprocess.CalledProcessError as exc: 1484515ffdfSMauro Carvalho Chehab sys.exit(f"Error running fc-list: {repr(exc)}") 1494515ffdfSMauro Carvalho Chehab 1504515ffdfSMauro Carvalho Chehab for line in result.stdout.splitlines(): 1514515ffdfSMauro Carvalho Chehab if 'variable=True' not in line: 1524515ffdfSMauro Carvalho Chehab continue 1534515ffdfSMauro Carvalho Chehab 1544515ffdfSMauro Carvalho Chehab match = self.re_cjk.search(line) 1554515ffdfSMauro Carvalho Chehab if match: 1564515ffdfSMauro Carvalho Chehab cjk_fonts.add(match.group(1)) 1574515ffdfSMauro Carvalho Chehab 1584515ffdfSMauro Carvalho Chehab return sorted(cjk_fonts) 1594515ffdfSMauro Carvalho Chehab 1604515ffdfSMauro Carvalho Chehab def check(self): 161*4d7f6319SMauro Carvalho Chehab """ 162*4d7f6319SMauro Carvalho Chehab Check for problems with CJK fonts. 163*4d7f6319SMauro Carvalho Chehab """ 1644515ffdfSMauro Carvalho Chehab 1654515ffdfSMauro Carvalho Chehab fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ") 1664515ffdfSMauro Carvalho Chehab if not fonts: 1674515ffdfSMauro Carvalho Chehab return None 1684515ffdfSMauro Carvalho Chehab 1694515ffdfSMauro Carvalho Chehab rel_file = os.path.relpath(__file__, os.getcwd()) 1704515ffdfSMauro Carvalho Chehab 1714515ffdfSMauro Carvalho Chehab msg = "=" * 77 + "\n" 1724515ffdfSMauro Carvalho Chehab msg += 'XeTeX is confused by "variable font" files listed below:\n' 1734515ffdfSMauro Carvalho Chehab msg += fonts + "\n" 1744515ffdfSMauro Carvalho Chehab msg += textwrap.dedent(f""" 1754515ffdfSMauro Carvalho Chehab For CJK pages in PDF, they need to be hidden from XeTeX by denylisting. 1764515ffdfSMauro Carvalho Chehab Or, CJK pages can be skipped by uninstalling texlive-xecjk. 1774515ffdfSMauro Carvalho Chehab 17892ea342fSMauro Carvalho Chehab For more info on denylisting, other options, and variable font, run: 17992ea342fSMauro Carvalho Chehab 18092ea342fSMauro Carvalho Chehab tools/docs/check-variable-fonts.py -h 1814515ffdfSMauro Carvalho Chehab """) 1824515ffdfSMauro Carvalho Chehab msg += "=" * 77 1834515ffdfSMauro Carvalho Chehab 1844515ffdfSMauro Carvalho Chehab return msg 185