From ee1334234213964158ada69413c5d504b2135b64 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 1 Dec 2017 23:50:39 -0800 Subject: [PATCH] Make _get_rgba_face actually always return a RGBA. _get_rgba_face is an internal function that is only use to set the graphicscontext's foreground color (in Line2D.draw); it is always effectively called as `gc.set_foreground(line._get_rgba_face(...), isRGBA=True)`. So it makes sense to have it actually always return a RGBA quadruplet, including when the color is "none" (in which case `mcolors.to_rgba` returns (0, 0, 0, 0) regardless of alpha, which works just fine). This removes the need for third party graphicscontexts to handle non-RGBA-quadruplets (specifically, None) even when set_foreground is actually called with isRGBA=True. --- lib/matplotlib/backends/backend_ps.py | 12 +++++++----- lib/matplotlib/cbook/__init__.py | 20 ++++++++++++++++++++ lib/matplotlib/lines.py | 26 ++++++++++---------------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index a2bb35d3e5bc..b386b3c44377 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -495,13 +495,13 @@ def draw_path(self, gc, path, transform, rgbFace=None): """ Draws a Path instance using the given affine transform. """ - clip = (rgbFace is None and gc.get_hatch_path() is None) + clip = rgbFace is None and gc.get_hatch_path() is None simplify = path.should_simplify and clip - ps = self._convert_path( - path, transform, clip=clip, simplify=simplify) + ps = self._convert_path(path, transform, clip=clip, simplify=simplify) self._draw_ps(ps, gc, rgbFace) - def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): + def draw_markers( + self, gc, marker_path, marker_trans, path, trans, rgbFace=None): """ Draw the markers defined by path at each of the positions in x and y. path coordinates are points, x and y coords will be @@ -510,7 +510,9 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None) if debugPS: self._pswriter.write('% draw_markers \n') if rgbFace: - if rgbFace[0]==rgbFace[1] and rgbFace[0]==rgbFace[2]: + if len(rgbFace) == 4 and rgbFace[3] == 0: + return + if rgbFace[0] == rgbFace[1] == rgbFace[2]: ps_color = '%1.3f setgray' % rgbFace[0] else: ps_color = '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace[:3] diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index 0b6a4968b113..e6a2a1d75e32 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -2766,3 +2766,23 @@ def _topmost_artist( in reverse order. """ return _cached_max(reversed(artists)) + + +def _str_equal(obj, s): + """Return whether *obj* is a string equal to string *s*. + + This helper solely exists to handle the case where *obj* is a numpy array, + because in such cases, a naive ``obj == s`` would yield an array, which + cannot be used in a boolean context. + """ + return isinstance(obj, six.string_types) and obj == s + + +def _str_lower_equal(obj, s): + """Return whether *obj* is a string equal, when lowercased, to string *s*. + + This helper solely exists to handle the case where *obj* is a numpy array, + because in such cases, a naive ``obj == s`` would yield an array, which + cannot be used in a boolean context. + """ + return isinstance(obj, six.string_types) and obj.lower() == s diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 043b3a5b7cd0..6dc7379fb6ea 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -13,7 +13,7 @@ import numpy as np -from . import artist, colors as mcolors, docstring, rcParams +from . import artist, cbook, colors as mcolors, docstring, rcParams from .artist import Artist, allow_rasterization from .cbook import ( _to_unmasked_float_array, iterable, is_numlike, ls_mapper, ls_mapper_r, @@ -793,16 +793,16 @@ def draw(self, renderer): rgbaFace = self._get_rgba_face() rgbaFaceAlt = self._get_rgba_face(alt=True) edgecolor = self.get_markeredgecolor() - if (isinstance(edgecolor, six.string_types) - and edgecolor.lower() == 'none'): + if cbook._str_lower_equal(edgecolor, "none"): gc.set_linewidth(0) gc.set_foreground(rgbaFace, isRGBA=True) else: gc.set_foreground(edgecolor) gc.set_linewidth(self._markeredgewidth) mec = self._markeredgecolor - if (isinstance(mec, six.string_types) and mec == 'auto' and - rgbaFace is not None): + if (cbook._str_equal(mec, "auto") + and not cbook._str_lower_equal( + self.get_markerfacecolor(), "none")): gc.set_alpha(rgbaFace[3]) else: gc.set_alpha(self.get_alpha()) @@ -828,8 +828,7 @@ def draw(self, renderer): marker_trans = marker.get_transform() w = renderer.points_to_pixels(self._markersize) - if (isinstance(marker.get_marker(), six.string_types) and - marker.get_marker() == ','): + if cbook._str_equal(marker.get_marker(), ","): gc.set_linewidth(0) else: # Don't scale for pixels, and don't stroke them @@ -843,8 +842,9 @@ def draw(self, renderer): if alt_marker_path: alt_marker_trans = marker.get_alt_transform() alt_marker_trans = alt_marker_trans.scale(w) - if (isinstance(mec, six.string_types) and mec == 'auto' and - rgbaFaceAlt is not None): + if (cbook._str_equal(mec, "auto") + and not cbook._str_lower_equal( + self.get_markerfacecoloralt(), "none")): gc.set_alpha(rgbaFaceAlt[3]) else: gc.set_alpha(self.get_alpha()) @@ -1257,13 +1257,7 @@ def update_from(self, other): self._drawstyle = other._drawstyle def _get_rgba_face(self, alt=False): - facecolor = self._get_markerfacecolor(alt=alt) - if (isinstance(facecolor, six.string_types) - and facecolor.lower() == 'none'): - rgbaFace = None - else: - rgbaFace = mcolors.to_rgba(facecolor, self._alpha) - return rgbaFace + return mcolors.to_rgba(self._get_markerfacecolor(alt=alt), self._alpha) def _get_rgba_ln_color(self, alt=False): return mcolors.to_rgba(self._color, self._alpha)