Skip to content

gap size for contour labels is poorly estimated #16153

Closed
@anntzer

Description

@anntzer

Bug report

Bug summary

The size of the gap for contour labels in contour plots is poorly estimated. (Noted while looking at #8819).

Code for reproduction

This uses a custom "very wide" font to make the problem more visible: download the font at https://www.1001fonts.com/20-db-font.html, put it somewhere where font_manager will find it, and run

from pylab import *
# You'll need to regen your font cache first.
rcParams['font.family'] = '20 db'
plt.figure()
x = np.arange(400).reshape((20,20))
c = plt.contour(x)
plt.clabel(c)
plt.show()

Actual outcome

bad

Expected outcome

good


The fix is actually not that hard (that's how I gen'd the "good" version)

diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py
index bc17765c5..dd07d9f22 100644
--- a/lib/matplotlib/contour.py
+++ b/lib/matplotlib/contour.py
@@ -236,20 +236,12 @@ class ContourLabeler:
         """
         if not isinstance(lev, str):
             lev = self.get_text(lev, fmt)
-        lev, ismath = text.Text()._preprocess_math(lev)
-        if ismath == 'TeX':
-            lw, _, _ = (texmanager.TexManager()
-                        .get_text_width_height_descent(lev, fsize))
-        elif ismath:
-            if not hasattr(self, '_mathtext_parser'):
-                self._mathtext_parser = mathtext.MathTextParser('bitmap')
-            img, _ = self._mathtext_parser.parse(lev, dpi=72,
-                                                 prop=self.labelFontProps)
-            _, lw = np.shape(img)  # at dpi=72, the units are PostScript points
-        else:
-            # width is much less than "font size"
-            lw = len(lev) * fsize * 0.6
-        return lw
+        fig = self.ax.figure
+        width = (text.Text(0, 0, lev,
+                           figure=fig, fontproperties=self.labelFontProps)
+                 .get_window_extent(fig.canvas.get_renderer()).width)
+        width *= 72 / fig.dpi
+        return width
 
     def set_label_props(self, label, text, color):
         """Set the label properties - color, fontsize, text."""

but this breaks a bunch of baseline images (unsurprisingly) so I'm going to combine this with other baseline-breaking cleanups I want to do on contour... Specifically, I plan to


Matplotlib version

  • Operating system: linux
  • Matplotlib version: master
  • Matplotlib backend (print(matplotlib.get_backend())): agg
  • Python version: 38
  • Jupyter version (if applicable):
  • Other libraries:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions