Skip to content

Commit 24a4b0e

Browse files
committed
Add a last resort font for missing glyphs
1 parent a3682f3 commit 24a4b0e

File tree

6 files changed

+123
-9
lines changed

6 files changed

+123
-9
lines changed

LICENSE/LICENSE_LAST_RESORT_FONT

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
Last Resort High-Efficiency Font License
2+
========================================
3+
4+
This Font Software is licensed under the SIL Open Font License,
5+
Version 1.1.
6+
7+
This license is copied below, and is also available with a FAQ at:
8+
http://scripts.sil.org/OFL
9+
10+
-----------------------------------------------------------
11+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
12+
-----------------------------------------------------------
13+
14+
PREAMBLE
15+
The goals of the Open Font License (OFL) are to stimulate worldwide
16+
development of collaborative font projects, to support the font
17+
creation efforts of academic and linguistic communities, and to
18+
provide a free and open framework in which fonts may be shared and
19+
improved in partnership with others.
20+
21+
The OFL allows the licensed fonts to be used, studied, modified and
22+
redistributed freely as long as they are not sold by themselves. The
23+
fonts, including any derivative works, can be bundled, embedded,
24+
redistributed and/or sold with any software provided that any reserved
25+
names are not used by derivative works. The fonts and derivatives,
26+
however, cannot be released under any other type of license. The
27+
requirement for fonts to remain under this license does not apply to
28+
any document created using the fonts or their derivatives.
29+
30+
DEFINITIONS
31+
"Font Software" refers to the set of files released by the Copyright
32+
Holder(s) under this license and clearly marked as such. This may
33+
include source files, build scripts and documentation.
34+
35+
"Reserved Font Name" refers to any names specified as such after the
36+
copyright statement(s).
37+
38+
"Original Version" refers to the collection of Font Software
39+
components as distributed by the Copyright Holder(s).
40+
41+
"Modified Version" refers to any derivative made by adding to,
42+
deleting, or substituting -- in part or in whole -- any of the
43+
components of the Original Version, by changing formats or by porting
44+
the Font Software to a new environment.
45+
46+
"Author" refers to any designer, engineer, programmer, technical
47+
writer or other person who contributed to the Font Software.
48+
49+
PERMISSION & CONDITIONS
50+
Permission is hereby granted, free of charge, to any person obtaining
51+
a copy of the Font Software, to use, study, copy, merge, embed,
52+
modify, redistribute, and sell modified and unmodified copies of the
53+
Font Software, subject to the following conditions:
54+
55+
1) Neither the Font Software nor any of its individual components, in
56+
Original or Modified Versions, may be sold by itself.
57+
58+
2) Original or Modified Versions of the Font Software may be bundled,
59+
redistributed and/or sold with any software, provided that each copy
60+
contains the above copyright notice and this license. These can be
61+
included either as stand-alone text files, human-readable headers or
62+
in the appropriate machine-readable metadata fields within text or
63+
binary files as long as those fields can be easily viewed by the user.
64+
65+
3) No Modified Version of the Font Software may use the Reserved Font
66+
Name(s) unless explicit written permission is granted by the
67+
corresponding Copyright Holder. This restriction only applies to the
68+
primary font name as presented to the users.
69+
70+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
71+
Software shall not be used to promote, endorse or advertise any
72+
Modified Version, except to acknowledge the contribution(s) of the
73+
Copyright Holder(s) and the Author(s) or with their explicit written
74+
permission.
75+
76+
5) The Font Software, modified or unmodified, in part or in whole,
77+
must be distributed entirely under this license, and must not be
78+
distributed under any other license. The requirement for fonts to
79+
remain under this license does not apply to any document created using
80+
the Font Software.
81+
82+
TERMINATION
83+
This license becomes null and void if any of the above conditions are
84+
not met.
85+
86+
DISCLAIMER
87+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
88+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
89+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
90+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
91+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
92+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
93+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
94+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
95+
OTHER DEALINGS IN THE FONT SOFTWARE.
96+
97+
SPDX-License-Identifier: OFL-1.1

lib/matplotlib/font_manager.py

+19-9
Original file line numberDiff line numberDiff line change
@@ -1552,17 +1552,26 @@ def is_opentype_cff_font(filename):
15521552

15531553

15541554
@lru_cache(64)
1555-
def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id):
1555+
def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id,
1556+
enable_last_resort):
15561557
first_fontpath, *rest = font_filepaths
1558+
fallback_list = [
1559+
ft2font.FT2Font(fpath, hinting_factor, _kerning_factor=_kerning_factor)
1560+
for fpath in rest
1561+
]
1562+
# Add Last Resort font so we always have glyphs regardless of font.
1563+
if enable_last_resort:
1564+
path = _cached_realpath(
1565+
cbook._get_data_path('fonts', 'ttf', 'LastResortHE-Regular.ttf'))
1566+
last_resort = ft2font.FT2Font(path, hinting_factor,
1567+
_kerning_factor=_kerning_factor)
1568+
# Ensure we are using the right charmap; FreeType picks the Unicode one
1569+
# by default, but this exists only for Windows, and is empty.
1570+
last_resort.set_charmap(0)
1571+
fallback_list.append(last_resort)
15571572
return ft2font.FT2Font(
15581573
first_fontpath, hinting_factor,
1559-
_fallback_list=[
1560-
ft2font.FT2Font(
1561-
fpath, hinting_factor,
1562-
_kerning_factor=_kerning_factor
1563-
)
1564-
for fpath in rest
1565-
],
1574+
_fallback_list=fallback_list,
15661575
_kerning_factor=_kerning_factor
15671576
)
15681577

@@ -1618,7 +1627,8 @@ def get_font(font_filepaths, hinting_factor=None):
16181627
hinting_factor,
16191628
_kerning_factor=mpl.rcParams['text.kerning_factor'],
16201629
# also key on the thread ID to prevent segfaults with multi-threading
1621-
thread_id=threading.get_ident()
1630+
thread_id=threading.get_ident(),
1631+
enable_last_resort=mpl.rcParams['font.enable_last_resort'],
16221632
)
16231633

16241634

Binary file not shown.

lib/matplotlib/mpl-data/matplotlibrc

+5
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@
278278
#font.fantasy: Chicago, Charcoal, Impact, Western, xkcd script, fantasy
279279
#font.monospace: DejaVu Sans Mono, Bitstream Vera Sans Mono, Computer Modern Typewriter, Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace
280280

281+
## If font.enable_last_resort is True, then Unicode Consortium's Last Resort
282+
## font will be appended to all font selections. This ensures that there will
283+
## always be a glyph displayed.
284+
#font.enable_last_resort: true
285+
281286

282287
## ***************************************************************************
283288
## * TEXT *

lib/matplotlib/rcsetup.py

+1
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ def _convert_validator_spec(key, conv):
10021002
"boxplot.meanprops.linewidth": validate_float,
10031003

10041004
## font props
1005+
"font.enable_last_resort": validate_bool,
10051006
"font.family": validate_stringlist, # used by text object
10061007
"font.style": validate_string,
10071008
"font.variant": validate_string,

lib/matplotlib/tests/test_text.py

+1
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,7 @@ def test_pdf_kerning():
823823

824824

825825
def test_unsupported_script(recwarn):
826+
plt.rcParams['font.enable_last_resort'] = False
826827
fig = plt.figure()
827828
t = fig.text(.5, .5, "\N{BENGALI DIGIT ZERO}")
828829
fig.canvas.draw()

0 commit comments

Comments
 (0)