Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b5eca56

Browse files
authored
Merge pull request #18080 from jkseppan/type1-rounding
MNT: Reduce numerical precision in Type 1 fonts
2 parents cb0654d + 9225aec commit b5eca56

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

lib/matplotlib/cbook/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,3 +2383,11 @@ def _setup_new_guiapp():
23832383
except OSError:
23842384
_c_internal_utils.Win32_SetCurrentProcessExplicitAppUserModelID(
23852385
"matplotlib")
2386+
2387+
2388+
def format_approx(number, precision):
2389+
"""
2390+
Format the number with at most the number of decimals given as precision.
2391+
Remove trailing zeros and possibly the decimal point.
2392+
"""
2393+
return f'{number:.{precision}f}'.rstrip('0').rstrip('.') or '0'

lib/matplotlib/tests/test_cbook.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,3 +741,15 @@ def verify_pre_post_state(obj):
741741
assert a.static == 'static'
742742

743743
verify_pre_post_state(a)
744+
745+
746+
def test_format_approx():
747+
f = cbook.format_approx
748+
assert f(0, 1) == '0'
749+
assert f(0, 2) == '0'
750+
assert f(0, 3) == '0'
751+
assert f(-0.0123, 1) == '-0'
752+
assert f(1e-7, 5) == '0'
753+
assert f(0.0012345600001, 5) == '0.00123'
754+
assert f(-0.0012345600001, 5) == '-0.00123'
755+
assert f(0.0012345600001, 8) == f(0.0012345600001, 10) == '0.00123456'

lib/matplotlib/tests/test_type1font.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_Type1Font():
2929
'+ /FontName /CMR10_Slant_1000 def',
3030
# Alters FontMatrix
3131
'- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def',
32-
'+ /FontMatrix [0.001 0.0 0.001 0.001 0.0 0.0]readonly def',
32+
'+ /FontMatrix [0.001 0 0.001 0.001 0 0]readonly def',
3333
# Alters ItalicAngle
3434
'- /ItalicAngle 0 def',
3535
'+ /ItalicAngle -45.0 def'):
@@ -47,5 +47,23 @@ def test_Type1Font():
4747
'+ /FontName /CMR10_Extend_500 def',
4848
# Alters FontMatrix
4949
'- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def',
50-
'+ /FontMatrix [0.0005 0.0 0.0 0.001 0.0 0.0]readonly def'):
50+
'+ /FontMatrix [0.0005 0 0 0.001 0 0]readonly def'):
5151
assert line in diff, 'diff to condensed font must contain %s' % line
52+
53+
54+
def test_overprecision():
55+
# We used to output too many digits in FontMatrix entries and
56+
# ItalicAngle, which could make Type-1 parsers unhappy.
57+
filename = os.path.join(os.path.dirname(__file__), 'cmr10.pfb')
58+
font = t1f.Type1Font(filename)
59+
slanted = font.transform({'slant': .167})
60+
lines = slanted.parts[0].decode('ascii').splitlines()
61+
matrix, = [line[line.index('[')+1:line.index(']')]
62+
for line in lines if '/FontMatrix' in line]
63+
angle, = [word
64+
for line in lines if '/ItalicAngle' in line
65+
for word in line.split() if word[0] in '-0123456789']
66+
# the following used to include 0.00016700000000000002
67+
assert matrix == '0.001 0 0.000167 0.001 0 0'
68+
# and here we had -9.48090361795083
69+
assert angle == '-9.4809'

lib/matplotlib/type1font.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
import numpy as np
3131

32+
from matplotlib.cbook import format_approx
33+
3234

3335
# token types
3436
_TokenType = enum.Enum('_TokenType',
@@ -251,7 +253,10 @@ def fontname(name):
251253
return result
252254

253255
def italicangle(angle):
254-
return b'%a' % (float(angle) - np.arctan(slant) / np.pi * 180)
256+
return b'%a' % round(
257+
float(angle) - np.arctan(slant) / np.pi * 180,
258+
5
259+
)
255260

256261
def fontmatrix(array):
257262
array = array.lstrip(b'[').rstrip(b']').split()
@@ -265,10 +270,9 @@ def fontmatrix(array):
265270
newmatrix = np.dot(modifier, oldmatrix)
266271
array[::2] = newmatrix[0:3, 0]
267272
array[1::2] = newmatrix[0:3, 1]
268-
# Not directly using `b'%a' % x for x in array` for now as that
269-
# produces longer reprs on numpy<1.14, causing test failures.
270-
as_string = '[' + ' '.join(str(x) for x in array) + ']'
271-
return as_string.encode('latin-1')
273+
return (
274+
'[%s]' % ' '.join(format_approx(x, 6) for x in array)
275+
).encode('ascii')
272276

273277
def replace(fun):
274278
def replacer(tokens):

0 commit comments

Comments
 (0)