You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
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):
 | 
						|
        _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):
 | 
						|
        _afm._parse_header(fh)
 | 
						|
 | 
						|
    assert len(caplog.records) == 1
 |