123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- from io import BytesIO
- import pytest
- import logging
- from matplotlib import afm
- from matplotlib import font_manager as fm
- # See note in afm.py re: use of comma as decimal separator in the
- # UnderlineThickness field and re: use of non-ASCII characters in the Notice
- # field.
- AFM_TEST_DATA = b"""StartFontMetrics 2.0
- Comment Comments are ignored.
- Comment Creation Date:Mon Nov 13 12:34:11 GMT 2017
- FontName MyFont-Bold
- EncodingScheme FontSpecific
- FullName My Font Bold
- FamilyName Test Fonts
- Weight Bold
- ItalicAngle 0.0
- IsFixedPitch false
- UnderlinePosition -100
- UnderlineThickness 56,789
- Version 001.000
- Notice Copyright \xa9 2017 No one.
- FontBBox 0 -321 1234 369
- StartCharMetrics 3
- C 0 ; WX 250 ; N space ; B 0 0 0 0 ;
- C 42 ; WX 1141 ; N foo ; B 40 60 800 360 ;
- C 99 ; WX 583 ; N bar ; B 40 -10 543 210 ;
- EndCharMetrics
- EndFontMetrics
- """
- def test_nonascii_str():
- # This tests that we also decode bytes as utf-8 properly.
- # Else, font files with non ascii characters fail to load.
- inp_str = "привет"
- byte_str = inp_str.encode("utf8")
- ret = afm._to_str(byte_str)
- assert ret == inp_str
- def test_parse_header():
- fh = BytesIO(AFM_TEST_DATA)
- header = afm._parse_header(fh)
- assert header == {
- b'StartFontMetrics': 2.0,
- b'FontName': 'MyFont-Bold',
- b'EncodingScheme': 'FontSpecific',
- b'FullName': 'My Font Bold',
- b'FamilyName': 'Test Fonts',
- b'Weight': 'Bold',
- b'ItalicAngle': 0.0,
- b'IsFixedPitch': False,
- b'UnderlinePosition': -100,
- b'UnderlineThickness': 56.789,
- b'Version': '001.000',
- b'Notice': b'Copyright \xa9 2017 No one.',
- b'FontBBox': [0, -321, 1234, 369],
- b'StartCharMetrics': 3,
- }
- def test_parse_char_metrics():
- fh = BytesIO(AFM_TEST_DATA)
- afm._parse_header(fh) # position
- metrics = afm._parse_char_metrics(fh)
- assert metrics == (
- {0: (250.0, 'space', [0, 0, 0, 0]),
- 42: (1141.0, 'foo', [40, 60, 800, 360]),
- 99: (583.0, 'bar', [40, -10, 543, 210]),
- },
- {'space': (250.0, 'space', [0, 0, 0, 0]),
- 'foo': (1141.0, 'foo', [40, 60, 800, 360]),
- 'bar': (583.0, 'bar', [40, -10, 543, 210]),
- })
- def test_get_familyname_guessed():
- fh = BytesIO(AFM_TEST_DATA)
- font = afm.AFM(fh)
- del font._header[b'FamilyName'] # remove FamilyName, so we have to guess
- assert font.get_familyname() == 'My Font'
- def test_font_manager_weight_normalization():
- font = afm.AFM(BytesIO(
- AFM_TEST_DATA.replace(b"Weight Bold\n", b"Weight Custom\n")))
- assert fm.afmFontProperty("", font).weight == "normal"
- @pytest.mark.parametrize(
- "afm_data",
- [
- b"""nope
- really nope""",
- b"""StartFontMetrics 2.0
- Comment Comments are ignored.
- Comment Creation Date:Mon Nov 13 12:34:11 GMT 2017
- FontName MyFont-Bold
- EncodingScheme FontSpecific""",
- ],
- )
- def test_bad_afm(afm_data):
- fh = BytesIO(afm_data)
- with pytest.raises(RuntimeError):
- header = afm._parse_header(fh)
- @pytest.mark.parametrize(
- "afm_data",
- [
- b"""StartFontMetrics 2.0
- Comment Comments are ignored.
- Comment Creation Date:Mon Nov 13 12:34:11 GMT 2017
- Aardvark bob
- FontName MyFont-Bold
- EncodingScheme FontSpecific
- StartCharMetrics 3""",
- b"""StartFontMetrics 2.0
- Comment Comments are ignored.
- Comment Creation Date:Mon Nov 13 12:34:11 GMT 2017
- ItalicAngle zero degrees
- FontName MyFont-Bold
- EncodingScheme FontSpecific
- StartCharMetrics 3""",
- ],
- )
- def test_malformed_header(afm_data, caplog):
- fh = BytesIO(afm_data)
- with caplog.at_level(logging.ERROR):
- header = afm._parse_header(fh)
- assert len(caplog.records) == 1
|