diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 62277f73ddc3..3fc97e757124 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -55,6 +55,7 @@ from matplotlib import is_interactive from matplotlib import get_backend from matplotlib._pylab_helpers import Gcf +from matplotlib import lines from matplotlib.transforms import Bbox, TransformedBbox, Affine2D @@ -771,14 +772,6 @@ class GraphicsContextBase(object): An abstract base class that provides color, line styles, etc... """ - # a mapping from dash styles to suggested offset, dash pairs - dashd = { - 'solid': (None, None), - 'dashed': (0, (6.0, 6.0)), - 'dashdot': (0, (3.0, 5.0, 1.0, 5.0)), - 'dotted': (0, (1.0, 3.0)), - } - def __init__(self): self._alpha = 1.0 self._forced_alpha = False # if True, _alpha overrides A from RGBA @@ -870,7 +863,16 @@ def get_dashes(self): Default value is None """ - return self._dashes + if rcParams['_internal.classic_mode']: + return self._dashes + else: + scale = max(1.0, self.get_linewidth()) + offset, dashes = self._dashes + if offset is not None: + offset = offset * scale + if dashes is not None: + dashes = [x * scale for x in dashes] + return offset, dashes def get_forced_alpha(self): """ @@ -1047,21 +1049,12 @@ def set_linewidth(self, w): def set_linestyle(self, style): """ Set the linestyle to be one of ('solid', 'dashed', 'dashdot', - 'dotted'). One may specify customized dash styles by providing - a tuple of (offset, dash pairs). For example, the predefiend - linestyles have following values.: - - 'dashed' : (0, (6.0, 6.0)), - 'dashdot' : (0, (3.0, 5.0, 1.0, 5.0)), - 'dotted' : (0, (1.0, 3.0)), + 'dotted'). These are defined in the rcParams + `lines.dashed_pattern`, `lines.dashdot_pattern` and + `lines.dotted_pattern`. One may also specify customized dash + styles by providing a tuple of (offset, dash pairs). """ - - if style in self.dashd: - offset, dashes = self.dashd[style] - elif isinstance(style, tuple): - offset, dashes = style - else: - raise ValueError('Unrecognized linestyle: %s' % str(style)) + offset, dashes = lines.get_dash_pattern(style) self._linestyle = style self.set_dashes(offset, dashes) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 7032bce22a21..3bdf84ba1245 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -28,6 +28,7 @@ import matplotlib.path as mpath from matplotlib import _path import matplotlib.mlab as mlab +import matplotlib.lines as mlines CIRCLE_AREA_FACTOR = 1.0 / np.sqrt(np.pi) @@ -531,23 +532,16 @@ def set_linestyle(self, ls): The line style. """ try: - dashd = backend_bases.GraphicsContextBase.dashd if cbook.is_string_like(ls): ls = cbook.ls_mapper.get(ls, ls) - if ls in dashd: - dashes = [dashd[ls]] - else: - raise ValueError() + dashes = [mlines.get_dash_pattern(ls)] elif cbook.iterable(ls): try: dashes = [] for x in ls: if cbook.is_string_like(x): x = cbook.ls_mapper.get(x, x) - if x in dashd: - dashes.append(dashd[x]) - else: - raise ValueError() + dashes.append(mlines.get_dash_pattern(x)) elif cbook.iterable(x) and len(x) == 2: dashes.append(x) else: diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index e8a032b9c2fa..3a671e2b3c9e 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -36,6 +36,24 @@ from matplotlib import _path +def get_dash_pattern(style): + """ + Given a dash pattern name from 'solid', 'dashed', 'dashdot' or + 'dotted', returns the (offset, dashes) pattern. + """ + if style == 'solid': + offset, dashes = None, None + elif style in ['dashed', 'dashdot', 'dotted']: + offset = 0 + dashes = tuple(rcParams['lines.{}_pattern'.format(style)]) + elif isinstance(style, tuple): + offset, dashes = style + else: + raise ValueError('Unrecognized linestyle: %s' % str(style)) + + return offset, dashes + + def segment_hits(cx, cy, x, y, radius): """ Determine if any line segments are within radius of a diff --git a/lib/matplotlib/mpl-data/stylelib/classic.mplstyle b/lib/matplotlib/mpl-data/stylelib/classic.mplstyle index 62de031f6db6..c5cdb660cd63 100644 --- a/lib/matplotlib/mpl-data/stylelib/classic.mplstyle +++ b/lib/matplotlib/mpl-data/stylelib/classic.mplstyle @@ -15,6 +15,9 @@ lines.dash_capstyle : butt # butt|round|projecting lines.solid_joinstyle : round # miter|round|bevel lines.solid_capstyle : projecting # butt|round|projecting lines.antialiased : True # render lines in antialiased (no jaggies) +lines.dashed_pattern : 6, 6 +lines.dashdot_pattern : 3, 5, 1, 5 +lines.dotted_pattern : 1, 3 ### Marker props markers.fillstyle: full diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index f8c239867087..46802d4b3f63 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -275,18 +275,18 @@ def validate_maskedarray(v): class validate_nseq_float(object): - def __init__(self, n): + def __init__(self, n=None): self.n = n def __call__(self, s): """return a seq of n floats or raise""" if isinstance(s, six.string_types): - s = s.split(',') + s = [x.strip() for x in s.split(',')] err_msg = _str_err_msg else: err_msg = _seq_err_msg - if len(s) != self.n: + if self.n is not None and len(s) != self.n: raise ValueError(err_msg.format(n=self.n, num=len(s), s=s)) try: @@ -296,18 +296,18 @@ def __call__(self, s): class validate_nseq_int(object): - def __init__(self, n): + def __init__(self, n=None): self.n = n def __call__(self, s): """return a seq of n ints or raise""" if isinstance(s, six.string_types): - s = s.split(',') + s = [x.strip() for x in s.split(',')] err_msg = _str_err_msg else: err_msg = _seq_err_msg - if len(s) != self.n: + if self.n is not None and len(s) != self.n: raise ValueError(err_msg.format(n=self.n, num=len(s), s=s)) try: @@ -836,6 +836,9 @@ def validate_hist_bins(s): 'lines.solid_joinstyle': ['round', validate_joinstyle], 'lines.dash_capstyle': ['butt', validate_capstyle], 'lines.solid_capstyle': ['projecting', validate_capstyle], + 'lines.dashed_pattern': [[2.8, 1.2], validate_nseq_float()], + 'lines.dashdot_pattern': [[4.8, 1.2, 0.8, 1.2], validate_nseq_float()], + 'lines.dotted_pattern': [[1.2, 0.6], validate_nseq_float()], # marker props 'markers.fillstyle': ['full', validate_fillstyle], diff --git a/matplotlibrc.template b/matplotlibrc.template index f52ea5794772..00a3fccb1979 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -90,6 +90,11 @@ backend : $TEMPLATE_BACKEND #lines.solid_capstyle : projecting # butt|round|projecting #lines.antialiased : True # render lines in antialiased (no jaggies) +# The three standard dash patterns. These are scaled by the linewidth. +#lines.dashed_pattern : 2.8, 1.2 +#lines.dashdot_pattern : 4.8, 1.2, 0.8, 1.2 +#lines.dotted_pattern : 1.2, 0.6 + #markers.fillstyle: full # full|left|right|bottom|top|none ### PATCHES diff --git a/src/py_converters.cpp b/src/py_converters.cpp index fee7bf8ad463..631763bbc37a 100644 --- a/src/py_converters.cpp +++ b/src/py_converters.cpp @@ -476,7 +476,7 @@ int convert_gcagg(PyObject *pygc, void *gcp) convert_from_attr(pygc, "_antialiased", &convert_bool, &gc->isaa) && convert_from_attr(pygc, "_capstyle", &convert_cap, &gc->cap) && convert_from_attr(pygc, "_joinstyle", &convert_join, &gc->join) && - convert_from_attr(pygc, "_dashes", &convert_dashes, &gc->dashes) && + convert_from_method(pygc, "get_dashes", &convert_dashes, &gc->dashes) && convert_from_attr(pygc, "_cliprect", &convert_rect, &gc->cliprect) && convert_from_method(pygc, "get_clip_path", &convert_clippath, &gc->clippath) && convert_from_method(pygc, "get_snap", &convert_snap, &gc->snap_mode) &&
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: