Skip to content

Commit

Permalink
Merge pull request #5926 from mdboom/new-dash-styles
Browse files Browse the repository at this point in the history
Fix #5917. New dash patterns. Scale dashes by lw
  • Loading branch information
efiring authored and tacaswell committed Feb 8, 2016
1 parent bb6978c commit 069785d
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 39 deletions.
39 changes: 16 additions & 23 deletions lib/matplotlib/backend_bases.py
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 3 additions & 9 deletions lib/matplotlib/collections.py
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions lib/matplotlib/lines.py
Expand Up @@ -37,6 +37,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
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
15 changes: 9 additions & 6 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
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 069785d

Please sign in to comment.