diff --git a/doc/api/api_changes.rst b/doc/api/api_changes.rst
index 50fd30a70bbf..d4fbf5bd2689 100644
--- a/doc/api/api_changes.rst
+++ b/doc/api/api_changes.rst
@@ -10,6 +10,30 @@ out what caused the breakage and how to fix it by updating your code.
For new features that were added to Matplotlib, please see
:ref:`whats-new`.
+API Changes in 2.0.1
+====================
+
+Extensions to `matplotlib.backend_bases.GraphicsContextBase`
+------------------------------------------------------------
+
+To better support controlling the color of hatches, the method
+`matplotlib.backend_bases.GraphicsContextBase.set_hatch_color` was
+added to the expected API of ``GraphicsContext`` classes. Calls to
+this method are currently wrapped with a ``try:...except Attribute:``
+block to preserve back-compatibility with any third-party backends
+which do not extend `~matplotlib.backend_bases.GraphicsContextBase`.
+
+This value can be accessed in the backends via
+`matplotlib.backend_bases.GraphicsContextBase.get_hatch_color` (which
+was added in 2.0 see :ref:`gc_get_hatch_color_wn`) and should be used
+to color the hatches.
+
+In the future there may also be ``hatch_linewidth`` and
+``hatch_density`` related methods added. It is encouraged, but not
+required that third-party backends extend
+`~matplotlib.backend_bases.GraphicsContextBase` to make adapting to
+these changes easier.
+
API Changes in 2.0.0
====================
diff --git a/doc/users/dflt_style_changes.rst b/doc/users/dflt_style_changes.rst
index 8c0422a70a0a..f419d3bd368a 100644
--- a/doc/users/dflt_style_changes.rst
+++ b/doc/users/dflt_style_changes.rst
@@ -617,20 +617,24 @@ To restore the previous behavior explicitly pass the keyword argument
Hatching
========
-The color and width of the lines in a hatch pattern are now configurable by the
-rcParams `hatch.color` and `hatch.linewidth`, with defaults of black and 1
-point, respectively. The old behaviour for the color was to apply the edge
-color or use black, depending on the artist; the old behavior for the line
-width was different depending on backend:
+
+The color of the lines in the hatch is now determined by
+
+ - If an edge color is explicitly set, use that for the hatch color
+ - If the edge color is not explicitly set, use ``rcParam['hatch.color']`` which
+ is looked up at artist creation time.
+
+The width of the lines in a hatch pattern is now configurable by the
+rcParams `hatch.linewidth`, which defaults to 1 point. The old
+behavior for the line width was different depending on backend:
- PDF: 0.1 pt
- SVG: 1.0 pt
- PS: 1 px
- Agg: 1 px
-The old color behavior can not be restored. The old line width behavior can not
-be restored across all backends simultaneously, but can be restored for a
-single backend by setting::
+The old line width behavior can not be restored across all backends
+simultaneously, but can be restored for a single backend by setting::
mpl.rcParams['hatch.linewidth'] = 0.1 # previous pdf hatch linewidth
mpl.rcParams['hatch.linewidth'] = 1.0 # previous svg hatch linewidth
@@ -643,7 +647,7 @@ The behavior of the PS and Agg backends was DPI dependent, thus::
mpl.rcParams['hatch.linewidth'] = 1.0 / dpi # previous ps and Agg hatch linewidth
-There is no API level control of the hatch color or linewidth.
+There is no direct API level control of the hatch color or linewidth.
Hatching patterns are now rendered at a consistent density, regardless of DPI.
Formerly, high DPI figures would be more dense than the default, and low DPI
diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst
index ee7c89f09412..daef2a3d2fb9 100644
--- a/doc/users/whats_new.rst
+++ b/doc/users/whats_new.rst
@@ -313,6 +313,20 @@ value of ``None`` instead of ``2``. If ``None`` is given as ``zorder``,
:func:`streamplot` has a default ``zorder`` of
``matplotlib.lines.Line2D.zorder``.
+.. _gc_get_hatch_color_wn:
+
+Extension to `matplotlib.backend_bases.GraphicsContextBase`
+-----------------------------------------------------------
+
+To support standardizing hatch behavior across the backends we ship
+the `matplotlib.backend_bases.GraphicsContextBase.get_hatch_color`
+method as added to `matplotlib.backend_bases.GraphicsContextBase`.
+This is only used during the render process in the backends we ship so
+will not break any third-party backends.
+
+If you maintain a third-party backend which extends
+`~matplotlib.backend_bases.GraphicsContextBase` this method is now
+available to you and should be used to color hatch patterns.
Previous Whats New
==================
diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py
index 40c70423a090..6c22a9d68293 100644
--- a/lib/matplotlib/backend_bases.py
+++ b/lib/matplotlib/backend_bases.py
@@ -817,6 +817,8 @@ def copy_properties(self, gc):
self._linewidth = gc._linewidth
self._rgb = gc._rgb
self._hatch = gc._hatch
+ self._hatch_color = gc._hatch_color
+ self._hatch_linewidth = gc._hatch_linewidth
self._url = gc._url
self._gid = gc._gid
self._snap = gc._snap
@@ -1111,6 +1113,12 @@ def get_hatch_color(self):
"""
return self._hatch_color
+ def set_hatch_color(self, hatch_color):
+ """
+ sets the color to use for hatching.
+ """
+ self._hatch_color = hatch_color
+
def get_hatch_linewidth(self):
"""
Gets the linewidth to use for hatching.
diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py
index 015f71a659c8..47b49e5418e9 100644
--- a/lib/matplotlib/backends/backend_pdf.py
+++ b/lib/matplotlib/backends/backend_pdf.py
@@ -2210,14 +2210,14 @@ def alpha_cmd(self, alpha, forced, effective_alphas):
name = self.file.alphaState(effective_alphas)
return [name, Op.setgstate]
- def hatch_cmd(self, hatch):
+ def hatch_cmd(self, hatch, hatch_color):
if not hatch:
if self._fillcolor is not None:
return self.fillcolor_cmd(self._fillcolor)
else:
return [Name('DeviceRGB'), Op.setcolorspace_nonstroke]
else:
- hatch_style = (self._hatch_color, self._fillcolor, hatch)
+ hatch_style = (hatch_color, self._fillcolor, hatch)
name = self.file.hatchPattern(hatch_style)
return [Name('Pattern'), Op.setcolorspace_nonstroke,
name, Op.setcolor_nonstroke]
@@ -2281,7 +2281,8 @@ def clip_cmd(self, cliprect, clippath):
(('_linewidth',), linewidth_cmd),
(('_dashes',), dash_cmd),
(('_rgb',), rgb_cmd),
- (('_hatch',), hatch_cmd), # must come after fillcolor and rgb
+ # must come after fillcolor and rgb
+ (('_hatch', '_hatch_color'), hatch_cmd),
)
# TODO: _linestyle
@@ -2312,7 +2313,7 @@ def delta(self, other):
break
# Need to update hatching if we also updated fillcolor
- if params == ('_hatch',) and fill_performed:
+ if params == ('_hatch', '_hatch_color') and fill_performed:
different = True
if different:
diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py
index 4da0d66663e5..ee6bb598c629 100644
--- a/lib/matplotlib/collections.py
+++ b/lib/matplotlib/collections.py
@@ -136,6 +136,7 @@ def __init__(self,
self._linewidths = [0]
self._is_filled = True # May be modified by set_facecolor().
+ self._hatch_color = mcolors.to_rgba(mpl.rcParams['hatch.color'])
self.set_facecolor(facecolors)
self.set_edgecolor(edgecolors)
self.set_linewidth(linewidths)
@@ -293,6 +294,12 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not support setting the "
+ "hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
@@ -690,12 +697,15 @@ def get_edgecolor(self):
get_edgecolors = get_edgecolor
def _set_edgecolor(self, c):
+ set_hatch_color = True
if c is None:
if (mpl.rcParams['patch.force_edgecolor'] or
not self._is_filled or self._edge_default):
c = mpl.rcParams['patch.edgecolor']
else:
c = 'none'
+ set_hatch_color = False
+
self._is_stroked = True
try:
if c.lower() == 'none':
@@ -710,6 +720,8 @@ def _set_edgecolor(self, c):
except AttributeError:
pass
self._edgecolors = mcolors.to_rgba_array(c, self._alpha)
+ if set_hatch_color and len(self._edgecolors):
+ self._hatch_color = tuple(self._edgecolors[0])
self.stale = True
def set_edgecolor(self, c):
diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py
index 05be96ee9e21..bb9f23cd46d2 100644
--- a/lib/matplotlib/patches.py
+++ b/lib/matplotlib/patches.py
@@ -5,6 +5,7 @@
import six
from six.moves import map, zip
+import warnings
import math
@@ -113,10 +114,10 @@ def __init__(self,
if antialiased is None:
antialiased = mpl.rcParams['patch.antialiased']
+ self._hatch_color = colors.to_rgba(mpl.rcParams['hatch.color'])
self._fill = True # needed for set_facecolor call
if color is not None:
if (edgecolor is not None or facecolor is not None):
- import warnings
warnings.warn("Setting the 'color' property will override"
"the edgecolor or facecolor properties. ")
self.set_color(color)
@@ -288,13 +289,18 @@ def set_aa(self, aa):
return self.set_antialiased(aa)
def _set_edgecolor(self, color):
+ set_hatch_color = True
if color is None:
if (mpl.rcParams['patch.force_edgecolor'] or
not self._fill or self._edge_default):
color = mpl.rcParams['patch.edgecolor']
else:
color = 'none'
+ set_hatch_color = False
+
self._edgecolor = colors.to_rgba(color, self._alpha)
+ if set_hatch_color:
+ self._hatch_color = self._edgecolor
self.stale = True
def set_edgecolor(self, color):
@@ -545,6 +551,12 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not have support for "
+ "setting the hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
@@ -4286,6 +4298,13 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ if self._hatch_color is not None:
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not support setting the "
+ "hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
diff --git a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.pdf b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.pdf
index 9e2b78a1807f..054fe8d8264f 100644
Binary files a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.pdf and b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.pdf differ
diff --git a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.png b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.png
index 2af7a6b99227..cf2ebc38391d 100644
Binary files a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.png and b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.png differ
diff --git a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.svg b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.svg
index e03c19267d15..22c7a3044c35 100644
--- a/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.svg
+++ b/lib/matplotlib/tests/baseline_images/test_artist/clip_path_clipping.svg
@@ -27,7 +27,7 @@ z
" style="fill:#ffffff;"/>
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: