diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index b5263f8fbe66..818b17a39801 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -265,6 +265,21 @@ def __init__(self, width, height, pswriter, imagedpi=72): self._path_collection_id = 0 self._character_tracker = _backend_pdf_ps.CharacterTracker() + self._logwarn_once = functools.lru_cache(None)(_log.warning) + + def _is_transparent(self, rgb_or_rgba): + if rgb_or_rgba is None: + return True # Consistent with rgbFace semantics. + elif len(rgb_or_rgba) == 4: + if rgb_or_rgba[3] == 0: + return True + if rgb_or_rgba[3] != 1: + self._logwarn_once( + "The PostScript backend does not support transparency; " + "partially transparent artists will be rendered opaque.") + return False + else: # len() == 3. + return False def set_color(self, r, g, b, store=True): if (r, g, b) != self.color: @@ -457,7 +472,7 @@ def draw_markers( ps_color = ( None - if _is_transparent(rgbFace) + if self._is_transparent(rgbFace) else '%1.3f setgray' % rgbFace[0] if rgbFace[0] == rgbFace[1] == rgbFace[2] else '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace[:3]) @@ -552,7 +567,7 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms, def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): # docstring inherited if not hasattr(self, "psfrag"): - _log.warning( + self._logwarn_once( "The PS backend determines usetex status solely based on " "rcParams['text.usetex'] and does not support having " "usetex=True only for some elements; this element will thus " @@ -589,7 +604,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): # docstring inherited - if _is_transparent(gc.get_rgb()): + if self._is_transparent(gc.get_rgb()): return # Special handling for fully transparent. if ismath == 'TeX': @@ -729,10 +744,10 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): """ write = self._pswriter.write mightstroke = (gc.get_linewidth() > 0 - and not _is_transparent(gc.get_rgb())) + and not self._is_transparent(gc.get_rgb())) if not mightstroke: stroke = False - if _is_transparent(rgbFace): + if self._is_transparent(rgbFace): fill = False hatch = gc.get_hatch() @@ -769,21 +784,6 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): write("grestore\n") -def _is_transparent(rgb_or_rgba): - if rgb_or_rgba is None: - return True # Consistent with rgbFace semantics. - elif len(rgb_or_rgba) == 4: - if rgb_or_rgba[3] == 0: - return True - if rgb_or_rgba[3] != 1: - _log.warning( - "The PostScript backend does not support transparency; " - "partially transparent artists will be rendered opaque.") - return False - else: # len() == 3. - return False - - @_api.deprecated("3.4", alternative="GraphicsContextBase") class GraphicsContextPS(GraphicsContextBase): def get_capstyle(self): diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index 57215367ab3b..a70145cc6d2d 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -149,10 +149,11 @@ def test_failing_latex(): @needs_usetex def test_partial_usetex(caplog): caplog.set_level("WARNING") - plt.figtext(.5, .5, "foo", usetex=True) + plt.figtext(.1, .1, "foo", usetex=True) + plt.figtext(.2, .2, "bar", usetex=True) plt.savefig(io.BytesIO(), format="ps") - assert caplog.records and all("as if usetex=False" in record.getMessage() - for record in caplog.records) + record, = caplog.records # asserts there's a single record. + assert "as if usetex=False" in record.getMessage() @image_comparison(["useafm.eps"])