From b3ef54ff75a02c6dd46be6e63848c6949c1e9c16 Mon Sep 17 00:00:00 2001 From: Hassan Kibirige Date: Wed, 23 Mar 2022 18:37:53 +0300 Subject: [PATCH 1/2] Fix path_effects to work on text with spaces only When a line of text contains no visual output (spaces only or empty newlines), there is no path to create for the effects. So, the data array for this non-path does not have the commonly expected shape for a path, so the logic bails with an error. The solution is, do not try to draw a path when the text string has only spaces and newlines. closes #22687 --- lib/matplotlib/patheffects.py | 3 +++ .../test_patheffects/spaces_and_newlines.png | Bin 0 -> 15040 bytes lib/matplotlib/tests/test_patheffects.py | 13 +++++++++++++ 3 files changed, 16 insertions(+) create mode 100644 lib/matplotlib/tests/baseline_images/test_patheffects/spaces_and_newlines.png diff --git a/lib/matplotlib/patheffects.py b/lib/matplotlib/patheffects.py index 416a26d3f651..41cc643ac024 100644 --- a/lib/matplotlib/patheffects.py +++ b/lib/matplotlib/patheffects.py @@ -138,6 +138,9 @@ def draw_path_collection(self, gc, master_transform, paths, *args, *args, **kwargs) def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath): + if not s.strip(): + return + # Implements the naive text drawing as is found in RendererBase. path, transform = self._get_text_path_transform(x, y, s, prop, angle, ismath) diff --git a/lib/matplotlib/tests/baseline_images/test_patheffects/spaces_and_newlines.png b/lib/matplotlib/tests/baseline_images/test_patheffects/spaces_and_newlines.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd4c1e8d7ff7646608d0f6fd6558df1cb49d3b0 GIT binary patch literal 15040 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 fUu>FO Date: Thu, 24 Mar 2022 09:00:26 +0300 Subject: [PATCH 2/2] Make an empty path_effect path for an empty string --- lib/matplotlib/patheffects.py | 3 --- lib/matplotlib/textpath.py | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/patheffects.py b/lib/matplotlib/patheffects.py index 41cc643ac024..416a26d3f651 100644 --- a/lib/matplotlib/patheffects.py +++ b/lib/matplotlib/patheffects.py @@ -138,9 +138,6 @@ def draw_path_collection(self, gc, master_transform, paths, *args, *args, **kwargs) def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath): - if not s.strip(): - return - # Implements the naive text drawing as is found in RendererBase. path, transform = self._get_text_path_transform(x, y, s, prop, angle, ismath) diff --git a/lib/matplotlib/textpath.py b/lib/matplotlib/textpath.py index 56c279dcc732..b7cb35a0e66e 100644 --- a/lib/matplotlib/textpath.py +++ b/lib/matplotlib/textpath.py @@ -129,6 +129,11 @@ def get_text_path(self, prop, s, ismath=False): verts.extend(verts1) codes.extend(codes1) + # Make sure an empty string or one with nothing to print + # (e.g. only spaces & newlines) will be valid/empty path + if not verts: + verts = np.empty((0, 2)) + return verts, codes def get_glyphs_with_font(self, font, s, glyph_map=None,