Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 712c393

Browse filesBrowse files
committed
fix exception when guessing the AFM familyname
1 parent 66967ab commit 712c393
Copy full SHA for 712c393

File tree

Expand file treeCollapse file tree

2 files changed

+77
-7
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+77
-7
lines changed

‎lib/matplotlib/afm.py

Copy file name to clipboardExpand all lines: lib/matplotlib/afm.py
+9-7Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,13 @@ def _parse_optional(fh):
312312
def parse_afm(fh):
313313
"""
314314
Parse the Adobe Font Metics file in file handle *fh*. Return value
315-
is a (*dhead*, *dcmetrics*, *dkernpairs*, *dcomposite*) tuple where
316-
*dhead* is a :func:`_parse_header` dict, *dcmetrics* is a
317-
:func:`_parse_composites` dict, *dkernpairs* is a
318-
:func:`_parse_kern_pairs` dict (possibly {}), and *dcomposite* is a
319-
:func:`_parse_composites` dict (possibly {})
315+
is a (*dhead*, *dcmetrics_ascii*, *dmetrics_name*, *dkernpairs*,
316+
*dcomposite*) tuple where
317+
*dhead* is a :func:`_parse_header` dict,
318+
*dcmetrics_ascii* and *dcmetrics_name* are the two resulting dicts
319+
from :func:`_parse_char_metrics`,
320+
*dkernpairs* is a :func:`_parse_kern_pairs` dict (possibly {}) and
321+
*dcomposite* is a :func:`_parse_composites` dict (possibly {})
320322
"""
321323
_sanity_check(fh)
322324
dhead = _parse_header(fh)
@@ -503,8 +505,8 @@ def get_familyname(self):
503505

504506
# FamilyName not specified so we'll make a guess
505507
name = self.get_fullname()
506-
extras = (br'(?i)([ -](regular|plain|italic|oblique|bold|semibold|'
507-
br'light|ultralight|extra|condensed))+$')
508+
extras = (r'(?i)([ -](regular|plain|italic|oblique|bold|semibold|'
509+
r'light|ultralight|extra|condensed))+$')
508510
return re.sub(extras, '', name)
509511

510512
@property

‎lib/matplotlib/tests/test_afm.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_afm.py
+68Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,35 @@
22

33
from __future__ import (absolute_import, division, print_function,
44
unicode_literals)
5+
from six import BytesIO
56

67
import matplotlib.afm as afm
78

89

10+
AFM_TEST_DATA = b"""StartFontMetrics 2.0
11+
Comment Comments are ignored.
12+
Comment Creation Date:Mon Nov 13 12:34:11 GMT 2017
13+
FontName MyFont-Bold
14+
EncodingScheme FontSpecific
15+
FullName My Font Bold
16+
FamilyName Test Fonts
17+
Weight Bold
18+
ItalicAngle 0.0
19+
IsFixedPitch false
20+
UnderlinePosition -100
21+
UnderlineThickness 50
22+
Version 001.000
23+
Notice Copyright (c) 2017 No one.
24+
FontBBox 0 -321 1234 369
25+
StartCharMetrics 3
26+
C 0 ; WX 250 ; N space ; B 0 0 0 0 ;
27+
C 42 ; WX 1141 ; N foo ; B 40 60 800 360 ;
28+
C 99 ; WX 583 ; N bar ; B 40 -10 543 210 ;
29+
EndCharMetrics
30+
EndFontMetrics
31+
"""
32+
33+
934
def test_nonascii_str():
1035
# This tests that we also decode bytes as utf-8 properly.
1136
# Else, font files with non ascii characters fail to load.
@@ -14,3 +39,46 @@ def test_nonascii_str():
1439

1540
ret = afm._to_str(byte_str)
1641
assert ret == inp_str
42+
43+
44+
def test_parse_header():
45+
fh = BytesIO(AFM_TEST_DATA)
46+
header = afm._parse_header(fh)
47+
assert header == {
48+
b'StartFontMetrics': 2.0,
49+
b'FontName': 'MyFont-Bold',
50+
b'EncodingScheme': 'FontSpecific',
51+
b'FullName': 'My Font Bold',
52+
b'FamilyName': 'Test Fonts',
53+
b'Weight': 'Bold',
54+
b'ItalicAngle': 0.0,
55+
b'IsFixedPitch': False,
56+
b'UnderlinePosition': -100,
57+
b'UnderlineThickness': 50,
58+
b'Version': '001.000',
59+
b'Notice': 'Copyright (c) 2017 No one.',
60+
b'FontBBox': [0, -321, 1234, 369],
61+
b'StartCharMetrics': 3,
62+
}
63+
64+
65+
def test_parse_char_metrics():
66+
fh = BytesIO(AFM_TEST_DATA)
67+
afm._parse_header(fh) # position
68+
metrics = afm._parse_char_metrics(fh)
69+
assert metrics == (
70+
{0: (250.0, 'space', [0, 0, 0, 0]),
71+
42: (1141.0, 'foo', [40, 60, 800, 360]),
72+
99: (583.0, 'bar', [40, -10, 543, 210]),
73+
},
74+
{'space': (250.0, [0, 0, 0, 0]),
75+
'foo': (1141.0, [40, 60, 800, 360]),
76+
'bar': (583.0, [40, -10, 543, 210]),
77+
})
78+
79+
80+
def test_get_familyname_guessed():
81+
fh = BytesIO(AFM_TEST_DATA)
82+
fm = afm.AFM(fh)
83+
del fm._header[b'FamilyName'] # remove FamilyName, so we have to guess
84+
assert fm.get_familyname() == 'My Font'

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.