Skip to content

Commit

Permalink
Fix #5917. New dash patterns. Scale dashes by lw
Browse files Browse the repository at this point in the history
  • Loading branch information
mdboom committed Jan 27, 2016
1 parent 2a4863c commit 04ffd42
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 31 deletions.
37 changes: 19 additions & 18 deletions lib/matplotlib/backend_bases.py
Expand Up @@ -771,14 +771,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
Expand Down Expand Up @@ -870,7 +862,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):
"""
Expand Down Expand Up @@ -1047,17 +1048,17 @@ 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]
if style == 'solid':
offset, dashes = None, None
elif style in ['dashed', 'dashdot', 'dotted']:
offset = 0
dashes = rcParams['lines.{}_pattern'.format(style)]
elif isinstance(style, tuple):
offset, dashes = style
else:
Expand Down
3 changes: 3 additions & 0 deletions lib/matplotlib/mpl-data/stylelib/classic.mplstyle
Expand Up @@ -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
Expand Down
28 changes: 16 additions & 12 deletions lib/matplotlib/rcsetup.py
Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -992,14 +995,15 @@ def validate_hist_bins(s):
'axes.formatter.use_mathtext': [False, validate_bool],
'axes.formatter.useoffset': [True, validate_bool],
'axes.unicode_minus': [True, validate_bool],
'axes.color_cycle': [['b', 'g', 'r', 'c', 'm', 'y', 'k'],
deprecate_axes_colorcycle], # cycle of plot
# line colors
# This entry can be either a cycler object or a
'axes.prop_cycle': [
ccycler('color',
['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
'#9467bd', '#8c564b', '#e377c2', '#7f7f7f',
'#bcbd22', '#17becf']),
validate_cycler], # This entry can be either a cycler object or a
# string repr of a cycler-object, which gets eval()'ed
# to create the object.
'axes.prop_cycle': [ccycler('color', 'bgrcmyk'),
validate_cycler],

# If 'data', axes limits are set close to the data.
# If 'round_numbers' axes limits are set to the nearest round numbers.
'axes.autolimit_mode': [
Expand Down
5 changes: 5 additions & 0 deletions matplotlibrc.template
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/py_converters.cpp
Expand Up @@ -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) &&
Expand Down

0 comments on commit 04ffd42

Please sign in to comment.