Skip to content

Commit 7909992

Browse files
committed
added _repr_png_ and resulting image is used for _repr_html_
1 parent af03a7d commit 7909992

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

lib/matplotlib/font_manager.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
# - setWeights function needs improvement
2424
# - 'light' is an invalid weight value, remove it.
2525

26+
from base64 import b64encode
2627
import dataclasses
2728
from functools import lru_cache
29+
from io import BytesIO
2830
import json
2931
import logging
3032
from numbers import Number
@@ -380,23 +382,20 @@ def findSystemFonts(fontpaths=None, fontext='ttf'):
380382
return [fname for fname in fontfiles if os.path.exists(fname)]
381383

382384

383-
def fontentry_helper_repr_html_(fontent):
384-
html = (f"<span style='font-family:{fontent.name}'>"
385-
f'{fontent.name}'
386-
'</span>')
385+
def fontentry_helper_repr_png_(fontent):
386+
from matplotlib.figure import Figure # Circular import.
387+
fig = Figure()
388+
font_path = Path(fontent.fname) if fontent.fname != '' else None
389+
fig.text(0, 0, fontent.name, font=font_path)
390+
with BytesIO() as buf:
391+
fig.savefig(buf, bbox_inches='tight', transparent=True)
392+
return buf.getvalue()
387393

388-
if fontent.fname == '':
389-
return html
390-
else:
391-
return ('<span>'
392-
'<style>'
393-
'@font-face { '
394-
f'font-family: {fontent.name}; '
395-
f'src: url({fontent.fname}); '
396-
'} '
397-
'</style>'
398-
f'{html}'
399-
'</span>')
394+
395+
def fontentry_helper_repr_html_(fontent):
396+
png_stream = fontentry_helper_repr_png_(fontent)
397+
png_b64 = b64encode(png_stream).decode()
398+
return f"<img src=\"data:image/png;base64, {png_b64}\" />"
400399

401400

402401
FontEntry = dataclasses.make_dataclass(
@@ -416,6 +415,7 @@ def fontentry_helper_repr_html_(fontent):
416415
It is used when populating the font lookup dictionary.
417416
""",
418417
'_repr_html_': lambda self: fontentry_helper_repr_html_(self),
418+
'_repr_png_': lambda self: fontentry_helper_repr_png_(self),
419419
}
420420
)
421421

lib/matplotlib/tests/test_font_manager.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import multiprocessing
33
import os
44
from pathlib import Path
5+
from PIL import Image
56
import shutil
67
import subprocess
78
import sys
@@ -270,12 +271,24 @@ def test_fontcache_thread_safe():
270271

271272

272273
def test_fontentry_dataclass():
273-
fontent1 = FontEntry(name='font-name')
274-
fontent2 = FontEntry(fname='/random', name='font-name')
274+
fontent = FontEntry(name='font-name')
275275

276-
assert type(fontent1.__doc__) == str
277-
assert '@font-face' not in fontent1._repr_html_()
278-
assert '@font-face' in fontent2._repr_html_()
276+
assert type(fontent.__doc__) == str
277+
278+
png = fontent._repr_png_()
279+
html = fontent._repr_html_()
280+
281+
img = Image.open(BytesIO(png))
282+
assert img.width > 0
283+
assert img.height > 0
284+
285+
assert html.startswith("<img src=\"data:image/png;base64")
286+
287+
288+
def test_fontentry_dataclass_invalid_path():
289+
with pytest.raises(FileNotFoundError):
290+
fontent = FontEntry(fname='/random', name='font-name')
291+
fontent._repr_html_()
279292

280293

281294
@pytest.mark.skipif(sys.platform == 'win32', reason='Linux or OS only')

0 commit comments

Comments
 (0)