|
13 | 13 |
|
14 | 14 | import numpy as np
|
15 | 15 | from numpy import ma
|
16 |
| -from matplotlib import verbose |
17 | 16 | from . import artist, colors as mcolors
|
18 | 17 | from .artist import Artist
|
19 | 18 | from .cbook import (iterable, is_string_like, is_numlike, ls_mapper_r,
|
20 |
| - pts_to_prestep, pts_to_poststep, pts_to_midstep) |
| 19 | + pts_to_prestep, pts_to_poststep, pts_to_midstep, ls_mapper, |
| 20 | + is_hashable) |
21 | 21 |
|
22 | 22 | from .path import Path
|
23 | 23 | from .transforms import Bbox, TransformedPath, IdentityTransform
|
|
36 | 36 | from matplotlib import _path
|
37 | 37 |
|
38 | 38 |
|
39 |
| -def get_dash_pattern(style): |
40 |
| - """ |
41 |
| - Given a dash pattern name from 'solid', 'dashed', 'dashdot' or |
42 |
| - 'dotted', returns the (offset, dashes) pattern. |
| 39 | +def _get_dash_pattern(style): |
| 40 | + """Convert linestyle -> dash pattern |
| 41 | +
|
43 | 42 | """
|
44 |
| - if style == 'solid': |
| 43 | + # go from short hand -> full strings |
| 44 | + if is_string_like(style) and is_hashable(style): |
| 45 | + style = ls_mapper.get(style, style) |
| 46 | + # un-dashed styles |
| 47 | + if style in ['solid', 'None']: |
45 | 48 | offset, dashes = None, None
|
| 49 | + # dashed styles |
46 | 50 | elif style in ['dashed', 'dashdot', 'dotted']:
|
47 | 51 | offset = 0
|
48 | 52 | dashes = tuple(rcParams['lines.{}_pattern'.format(style)])
|
| 53 | + # |
49 | 54 | elif isinstance(style, tuple):
|
50 | 55 | offset, dashes = style
|
51 | 56 | else:
|
52 | 57 | raise ValueError('Unrecognized linestyle: %s' % str(style))
|
53 | 58 |
|
| 59 | + # normalize offset to be positive and shorter than the dash cycle |
| 60 | + if dashes is not None and offset is not None: |
| 61 | + dsum = sum(dashes) |
| 62 | + if dsum: |
| 63 | + offset %= dsum |
| 64 | + |
54 | 65 | return offset, dashes
|
55 | 66 |
|
56 | 67 |
|
| 68 | +def _scale_dashes(offset, dashes, lw): |
| 69 | + if rcParams['_internal.classic_mode']: |
| 70 | + return offset, dashes |
| 71 | + scale = max(1.0, lw) |
| 72 | + scaled_offset = scaled_dashes = None |
| 73 | + if offset is not None: |
| 74 | + scaled_offset = offset * scale |
| 75 | + if dashes is not None: |
| 76 | + scaled_dashes = [x * scale if x is not None else None |
| 77 | + for x in dashes] |
| 78 | + |
| 79 | + return scaled_offset, scaled_dashes |
| 80 | + |
| 81 | + |
57 | 82 | def segment_hits(cx, cy, x, y, radius):
|
58 | 83 | """
|
59 | 84 | Determine if any line segments are within radius of a
|
@@ -360,10 +385,15 @@ def __init__(self, xdata, ydata,
|
360 | 385 |
|
361 | 386 | self._linestyles = None
|
362 | 387 | self._drawstyle = None
|
363 |
| - self._linewidth = None |
| 388 | + self._linewidth = linewidth |
364 | 389 |
|
| 390 | + # scaled dash + offset |
365 | 391 | self._dashSeq = None
|
366 | 392 | self._dashOffset = 0
|
| 393 | + # unscaled dash + offset |
| 394 | + # this is needed scaling the dash pattern by linewidth |
| 395 | + self._us_dashSeq = None |
| 396 | + self._us_dashOffset = 0 |
367 | 397 |
|
368 | 398 | self.set_linestyle(linestyle)
|
369 | 399 | self.set_drawstyle(drawstyle)
|
@@ -1013,9 +1043,13 @@ def set_linewidth(self, w):
|
1013 | 1043 | ACCEPTS: float value in points
|
1014 | 1044 | """
|
1015 | 1045 | w = float(w)
|
| 1046 | + |
1016 | 1047 | if self._linewidth != w:
|
1017 | 1048 | self.stale = True
|
1018 | 1049 | self._linewidth = w
|
| 1050 | + # rescale the dashes + offset |
| 1051 | + self._dashOffset, self._dashSeq = _scale_dashes( |
| 1052 | + self._us_dashOffset, self._us_dashSeq, self._linewidth) |
1019 | 1053 |
|
1020 | 1054 | def _split_drawstyle_linestyle(self, ls):
|
1021 | 1055 | '''Split drawstyle from linestyle string
|
@@ -1093,31 +1127,31 @@ def set_linestyle(self, ls):
|
1093 | 1127 | ls : { ``'-'``, ``'--'``, ``'-.'``, ``':'``} and more see description
|
1094 | 1128 | The line style.
|
1095 | 1129 | """
|
1096 |
| - if not is_string_like(ls): |
1097 |
| - if len(ls) != 2: |
1098 |
| - raise ValueError() |
1099 |
| - |
1100 |
| - self.set_dashes(ls[1]) |
1101 |
| - self._dashOffset = ls[0] |
1102 |
| - self._linestyle = "--" |
1103 |
| - return |
1104 |
| - ds, ls = self._split_drawstyle_linestyle(ls) |
1105 |
| - if ds is not None: |
1106 |
| - self.set_drawstyle(ds) |
1107 |
| - |
1108 |
| - if ls in [' ', '', 'none']: |
1109 |
| - ls = 'None' |
1110 |
| - |
1111 |
| - if ls not in self._lineStyles: |
1112 |
| - try: |
1113 |
| - ls = ls_mapper_r[ls] |
1114 |
| - except KeyError: |
1115 |
| - raise ValueError(("You passed in an invalid linestyle, " |
1116 |
| - "`{0}`. See " |
1117 |
| - "docs of Line2D.set_linestyle for " |
1118 |
| - "valid values.").format(ls)) |
| 1130 | + if is_string_like(ls): |
| 1131 | + ds, ls = self._split_drawstyle_linestyle(ls) |
| 1132 | + if ds is not None: |
| 1133 | + self.set_drawstyle(ds) |
| 1134 | + |
| 1135 | + if ls in [' ', '', 'none']: |
| 1136 | + ls = 'None' |
| 1137 | + |
| 1138 | + if ls not in self._lineStyles: |
| 1139 | + try: |
| 1140 | + ls = ls_mapper_r[ls] |
| 1141 | + except KeyError: |
| 1142 | + raise ValueError(("You passed in an invalid linestyle, " |
| 1143 | + "`{0}`. See " |
| 1144 | + "docs of Line2D.set_linestyle for " |
| 1145 | + "valid values.").format(ls)) |
| 1146 | + self._linestyle = ls |
| 1147 | + else: |
| 1148 | + self._linestyle = '--' |
1119 | 1149 |
|
1120 |
| - self._linestyle = ls |
| 1150 | + # get the unscaled dashes |
| 1151 | + self._us_dashOffset, self._us_dashSeq = _get_dash_pattern(ls) |
| 1152 | + # compute the linewidth scaled dashes |
| 1153 | + self._dashOffset, self._dashSeq = _scale_dashes( |
| 1154 | + self._us_dashOffset, self._us_dashSeq, self._linewidth) |
1121 | 1155 |
|
1122 | 1156 | @docstring.dedent_interpd
|
1123 | 1157 | def set_marker(self, marker):
|
@@ -1227,10 +1261,7 @@ def set_dashes(self, seq):
|
1227 | 1261 | if seq == (None, None) or len(seq) == 0:
|
1228 | 1262 | self.set_linestyle('-')
|
1229 | 1263 | else:
|
1230 |
| - self.set_linestyle('--') |
1231 |
| - if self._dashSeq != seq: |
1232 |
| - self.stale = True |
1233 |
| - self._dashSeq = seq # TODO: offset ignored for now |
| 1264 | + self.set_linestyle((0, seq)) |
1234 | 1265 |
|
1235 | 1266 | def _draw_lines(self, renderer, gc, path, trans):
|
1236 | 1267 | self._lineFunc(renderer, gc, path, trans)
|
@@ -1258,21 +1289,22 @@ def _draw_steps_mid(self, renderer, gc, path, trans):
|
1258 | 1289 |
|
1259 | 1290 | def _draw_solid(self, renderer, gc, path, trans):
|
1260 | 1291 | gc.set_linestyle('solid')
|
| 1292 | + gc.set_dashes(self._dashOffset, self._dashSeq) |
1261 | 1293 | renderer.draw_path(gc, path, trans)
|
1262 | 1294 |
|
1263 | 1295 | def _draw_dashed(self, renderer, gc, path, trans):
|
1264 | 1296 | gc.set_linestyle('dashed')
|
1265 |
| - if self._dashSeq is not None: |
1266 |
| - gc.set_dashes(self._dashOffset, self._dashSeq) |
1267 |
| - |
| 1297 | + gc.set_dashes(self._dashOffset, self._dashSeq) |
1268 | 1298 | renderer.draw_path(gc, path, trans)
|
1269 | 1299 |
|
1270 | 1300 | def _draw_dash_dot(self, renderer, gc, path, trans):
|
1271 | 1301 | gc.set_linestyle('dashdot')
|
| 1302 | + gc.set_dashes(self._dashOffset, self._dashSeq) |
1272 | 1303 | renderer.draw_path(gc, path, trans)
|
1273 | 1304 |
|
1274 | 1305 | def _draw_dotted(self, renderer, gc, path, trans):
|
1275 | 1306 | gc.set_linestyle('dotted')
|
| 1307 | + gc.set_dashes(self._dashOffset, self._dashSeq) |
1276 | 1308 | renderer.draw_path(gc, path, trans)
|
1277 | 1309 |
|
1278 | 1310 | def update_from(self, other):
|
|
0 commit comments