From 5cf6533cb9ca791e888265b381ee2b18c52d4db0 Mon Sep 17 00:00:00 2001 From: agra Date: Thu, 9 Dec 2021 23:04:48 -0500 Subject: [PATCH 1/5] created _repr_html_ for FontEntry objects --- lib/matplotlib/font_manager.py | 5 ++++- lib/matplotlib/tests/test_font_manager.py | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 9716e72b5330..ba7b307a87ef 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -395,7 +395,10 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): A class for storing Font properties. It is used when populating the font lookup dictionary. - """}) + """, + '_repr_html_': lambda self: f"{self.name}", # noqa: E501 + } +) def ttfFontProperty(font): diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index ee62120c1e37..6428d8ef80cc 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -11,7 +11,7 @@ import pytest from matplotlib.font_manager import ( - findfont, findSystemFonts, FontProperties, fontManager, json_dump, + findfont, findSystemFonts, FontEntry, FontProperties, fontManager, json_dump, json_load, get_font, is_opentype_cff_font, MSUserFontDirectories, _get_fontconfig_fonts) from matplotlib import pyplot as plt, rc_context @@ -266,3 +266,10 @@ def test_fontcache_thread_safe(): if proc.returncode: pytest.fail("The subprocess returned with non-zero exit status " f"{proc.returncode}.") + + +def test_fontentry_dataclass(): + entry = FontEntry(name="font-name") + + assert type(entry.__doc__) == str + assert entry._repr_html_() == "font-name" From 48053bbc44ee3709916c300c701f3891006ac367 Mon Sep 17 00:00:00 2001 From: agra Date: Thu, 9 Dec 2021 23:46:04 -0500 Subject: [PATCH 2/5] fixed flake8 issues --- lib/matplotlib/tests/test_font_manager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 6428d8ef80cc..82afec94e3e9 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -11,9 +11,9 @@ import pytest from matplotlib.font_manager import ( - findfont, findSystemFonts, FontEntry, FontProperties, fontManager, json_dump, - json_load, get_font, is_opentype_cff_font, MSUserFontDirectories, - _get_fontconfig_fonts) + findfont, findSystemFonts, FontEntry, FontProperties, fontManager, + json_dump, json_load, get_font, is_opentype_cff_font, + MSUserFontDirectories, _get_fontconfig_fonts) from matplotlib import pyplot as plt, rc_context has_fclist = shutil.which('fc-list') is not None @@ -272,4 +272,4 @@ def test_fontentry_dataclass(): entry = FontEntry(name="font-name") assert type(entry.__doc__) == str - assert entry._repr_html_() == "font-name" + assert entry._repr_html_() == "font-name" # noqa: E501 From 171d8d5c69b85dbea2ed2a84afe6daa493f783b0 Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 12 Dec 2021 13:54:16 -0500 Subject: [PATCH 3/5] added font-face style attribute to load custom fonts from local path --- lib/matplotlib/font_manager.py | 21 ++++++++++++++++++++- lib/matplotlib/tests/test_font_manager.py | 8 +++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index f8a91034c891..6497cc9702e5 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -380,6 +380,25 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): return [fname for fname in fontfiles if os.path.exists(fname)] +def fontentry_helper_repr_html_(fontent): + html = (f"" + f'{fontent.name}' + '') + + if fontent.fname == '': + return html + else: + return ('' + '' + f'{html}' + '') + + FontEntry = dataclasses.make_dataclass( 'FontEntry', [ ('fname', str, dataclasses.field(default='')), @@ -396,7 +415,7 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): It is used when populating the font lookup dictionary. """, - '_repr_html_': lambda self: f"{self.name}", # noqa: E501 + '_repr_html_': lambda self: fontentry_helper_repr_html_(self), } ) diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 3f0d346b8eb4..5df8cb8ef57c 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -270,10 +270,12 @@ def test_fontcache_thread_safe(): def test_fontentry_dataclass(): - entry = FontEntry(name="font-name") + fontent1 = FontEntry(name='font-name') + fontent2 = FontEntry(fname='/random', name='font-name') - assert type(entry.__doc__) == str - assert entry._repr_html_() == "font-name" # noqa: E501 + assert type(fontent1.__doc__) == str + assert '@font-face' not in fontent1._repr_html_() + assert '@font-face' in fontent2._repr_html_() @pytest.mark.skipif(sys.platform == 'win32', reason='Linux or OS only') From 7909992bc8f0d827794db4f5b24a825ba40625f9 Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 12 Dec 2021 22:09:49 -0500 Subject: [PATCH 4/5] added _repr_png_ and resulting image is used for _repr_html_ --- lib/matplotlib/font_manager.py | 32 +++++++++++------------ lib/matplotlib/tests/test_font_manager.py | 23 ++++++++++++---- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 6497cc9702e5..5eb726618faa 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -23,8 +23,10 @@ # - setWeights function needs improvement # - 'light' is an invalid weight value, remove it. +from base64 import b64encode import dataclasses from functools import lru_cache +from io import BytesIO import json import logging from numbers import Number @@ -380,23 +382,20 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): return [fname for fname in fontfiles if os.path.exists(fname)] -def fontentry_helper_repr_html_(fontent): - html = (f"" - f'{fontent.name}' - '') +def fontentry_helper_repr_png_(fontent): + from matplotlib.figure import Figure # Circular import. + fig = Figure() + font_path = Path(fontent.fname) if fontent.fname != '' else None + fig.text(0, 0, fontent.name, font=font_path) + with BytesIO() as buf: + fig.savefig(buf, bbox_inches='tight', transparent=True) + return buf.getvalue() - if fontent.fname == '': - return html - else: - return ('' - '' - f'{html}' - '') + +def fontentry_helper_repr_html_(fontent): + png_stream = fontentry_helper_repr_png_(fontent) + png_b64 = b64encode(png_stream).decode() + return f"" FontEntry = dataclasses.make_dataclass( @@ -416,6 +415,7 @@ def fontentry_helper_repr_html_(fontent): It is used when populating the font lookup dictionary. """, '_repr_html_': lambda self: fontentry_helper_repr_html_(self), + '_repr_png_': lambda self: fontentry_helper_repr_png_(self), } ) diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 5df8cb8ef57c..18678cb58306 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -2,6 +2,7 @@ import multiprocessing import os from pathlib import Path +from PIL import Image import shutil import subprocess import sys @@ -270,12 +271,24 @@ def test_fontcache_thread_safe(): def test_fontentry_dataclass(): - fontent1 = FontEntry(name='font-name') - fontent2 = FontEntry(fname='/random', name='font-name') + fontent = FontEntry(name='font-name') - assert type(fontent1.__doc__) == str - assert '@font-face' not in fontent1._repr_html_() - assert '@font-face' in fontent2._repr_html_() + assert type(fontent.__doc__) == str + + png = fontent._repr_png_() + html = fontent._repr_html_() + + img = Image.open(BytesIO(png)) + assert img.width > 0 + assert img.height > 0 + + assert html.startswith(" Date: Wed, 15 Dec 2021 23:51:04 -0500 Subject: [PATCH 5/5] modified tests to keep important items --- lib/matplotlib/tests/test_font_manager.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 18678cb58306..fb1119e33489 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -273,15 +273,12 @@ def test_fontcache_thread_safe(): def test_fontentry_dataclass(): fontent = FontEntry(name='font-name') - assert type(fontent.__doc__) == str - png = fontent._repr_png_() - html = fontent._repr_html_() - img = Image.open(BytesIO(png)) assert img.width > 0 assert img.height > 0 + html = fontent._repr_html_() assert html.startswith("