Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/lib/python/kdoc/latex_fonts.py
38186 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0-only
3
# Copyright (C) Akira Yokosawa, 2024
4
#
5
# Ported to Python by (c) Mauro Carvalho Chehab, 2025
6
7
"""
8
Detect problematic Noto CJK variable fonts.
9
10
For "make pdfdocs", reports of build errors of translations.pdf started
11
arriving early 2024 [1, 2]. It turned out that Fedora and openSUSE
12
tumbleweed have started deploying variable-font [3] format of "Noto CJK"
13
fonts [4, 5]. For PDF, a LaTeX package named xeCJK is used for CJK
14
(Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which
15
does not (and likely never will) understand variable fonts for historical
16
reasons.
17
18
The build error happens even when both of variable- and non-variable-format
19
fonts are found on the build system. To make matters worse, Fedora enlists
20
variable "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 more
22
likely to encounter the build errors.
23
24
This script is invoked from the error path of "make pdfdocs" and emits
25
suggestions if variable-font files of "Noto CJK" fonts are in the list of
26
fonts accessible from XeTeX.
27
28
References:
29
[1]: https://lore.kernel.org/r/[email protected]/
30
[2]: https://lore.kernel.org/r/[email protected]/
31
[3]: https://en.wikipedia.org/wiki/Variable_font
32
[4]: https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts
33
[5]: https://build.opensuse.org/request/show/1157217
34
35
#===========================================================================
36
Workarounds for building translations.pdf
37
#===========================================================================
38
39
* Denylist "variable font" Noto CJK fonts.
40
- Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with
41
tweaks if necessary. Remove leading "".
42
- Path of fontconfig/fonts.conf can be overridden by setting an env
43
variable FONTS_CONF_DENY_VF.
44
45
* Template:
46
-----------------------------------------------------------------
47
<?xml version="1.0"?>
48
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
49
<fontconfig>
50
<!--
51
Ignore variable-font glob (not to break xetex)
52
-->
53
<selectfont>
54
<rejectfont>
55
<!--
56
for Fedora
57
-->
58
<glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob>
59
<!--
60
for openSUSE tumbleweed
61
-->
62
<glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob>
63
</rejectfont>
64
</selectfont>
65
</fontconfig>
66
-----------------------------------------------------------------
67
68
The denylisting is activated for "make pdfdocs".
69
70
* For skipping CJK pages in PDF
71
- Uninstall texlive-xecjk.
72
Denylisting is not needed in this case.
73
74
* For printing CJK pages in PDF
75
- Need non-variable "Noto CJK" fonts.
76
* Fedora
77
- google-noto-sans-cjk-fonts
78
- google-noto-serif-cjk-fonts
79
* openSUSE tumbleweed
80
- Non-variable "Noto CJK" fonts are not available as distro packages
81
as of April, 2024. Fetch a set of font files from upstream Noto
82
CJK Font released at:
83
https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc
84
and at:
85
https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc
86
, then uncompress and deploy them.
87
- Remember to update fontconfig cache by running fc-cache.
88
89
!!! Caution !!!
90
Uninstalling "variable font" packages can be dangerous.
91
They might be depended upon by other packages important for your work.
92
Denylisting should be less invasive, as it is effective only while
93
XeLaTeX runs in "make pdfdocs".
94
"""
95
96
import os
97
import re
98
import subprocess
99
import textwrap
100
import sys
101
102
class LatexFontChecker:
103
"""
104
Detect problems with CJK variable fonts that affect PDF builds for
105
translations.
106
"""
107
108
def __init__(self, deny_vf=None):
109
if not deny_vf:
110
deny_vf = os.environ.get('FONTS_CONF_DENY_VF', "~/deny-vf")
111
112
self.environ = os.environ.copy()
113
self.environ['XDG_CONFIG_HOME'] = os.path.expanduser(deny_vf)
114
115
self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK")
116
117
def description(self):
118
return __doc__
119
120
def get_noto_cjk_vf_fonts(self):
121
"""Get Noto CJK fonts"""
122
123
cjk_fonts = set()
124
cmd = ["fc-list", ":", "file", "family", "variable"]
125
try:
126
result = subprocess.run(cmd,stdout=subprocess.PIPE,
127
stderr=subprocess.PIPE,
128
universal_newlines=True,
129
env=self.environ,
130
check=True)
131
132
except subprocess.CalledProcessError as exc:
133
sys.exit(f"Error running fc-list: {repr(exc)}")
134
135
for line in result.stdout.splitlines():
136
if 'variable=True' not in line:
137
continue
138
139
match = self.re_cjk.search(line)
140
if match:
141
cjk_fonts.add(match.group(1))
142
143
return sorted(cjk_fonts)
144
145
def check(self):
146
"""Check for problems with CJK fonts"""
147
148
fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ")
149
if not fonts:
150
return None
151
152
rel_file = os.path.relpath(__file__, os.getcwd())
153
154
msg = "=" * 77 + "\n"
155
msg += 'XeTeX is confused by "variable font" files listed below:\n'
156
msg += fonts + "\n"
157
msg += textwrap.dedent(f"""
158
For CJK pages in PDF, they need to be hidden from XeTeX by denylisting.
159
Or, CJK pages can be skipped by uninstalling texlive-xecjk.
160
161
For more info on denylisting, other options, and variable font, run:
162
163
tools/docs/check-variable-fonts.py -h
164
""")
165
msg += "=" * 77
166
167
return msg
168
169