|
| 1 | +import contextlib |
1 | 2 | import functools
|
2 | 3 | import math
|
3 | 4 | from numbers import Number
|
@@ -479,11 +480,15 @@ def get_hatch(self):
|
479 | 480 | 'Return the current hatching pattern'
|
480 | 481 | return self._hatch
|
481 | 482 |
|
482 |
| - @artist.allow_rasterization |
483 |
| - def draw(self, renderer): |
484 |
| - 'Draw the :class:`Patch` to the given *renderer*.' |
485 |
| - if not self.get_visible(): |
486 |
| - return |
| 483 | + @contextlib.contextmanager |
| 484 | + def _prepare_path_drawer(self, renderer): |
| 485 | + """ |
| 486 | + ``draw()`` helper factored out for sharing with `FancyArrowPatch`. |
| 487 | +
|
| 488 | + Yields a callable that can be called as a bound ``draw_path`` method |
| 489 | + except that the first argument (the ``GraphicsContext``) has already |
| 490 | + been suitably filled in. |
| 491 | + """ |
487 | 492 |
|
488 | 493 | renderer.open_group('patch', self.get_gid())
|
489 | 494 | gc = renderer.new_gc()
|
@@ -521,21 +526,33 @@ def draw(self, renderer):
|
521 | 526 | if self.get_sketch_params() is not None:
|
522 | 527 | gc.set_sketch_params(*self.get_sketch_params())
|
523 | 528 |
|
524 |
| - path = self.get_path() |
525 |
| - transform = self.get_transform() |
526 |
| - tpath = transform.transform_path_non_affine(path) |
527 |
| - affine = transform.get_affine() |
528 |
| - |
529 | 529 | if self.get_path_effects():
|
530 | 530 | from matplotlib.patheffects import PathEffectRenderer
|
531 | 531 | renderer = PathEffectRenderer(self.get_path_effects(), renderer)
|
532 | 532 |
|
533 |
| - renderer.draw_path(gc, tpath, affine, rgbFace) |
| 533 | + yield functools.partial(renderer.draw_path, gc) |
534 | 534 |
|
535 | 535 | gc.restore()
|
536 | 536 | renderer.close_group('patch')
|
537 | 537 | self.stale = False
|
538 | 538 |
|
| 539 | + @artist.allow_rasterization |
| 540 | + def draw(self, renderer): |
| 541 | + 'Draw the :class:`Patch` to the given *renderer*.' |
| 542 | + if not self.get_visible(): |
| 543 | + return |
| 544 | + |
| 545 | + with self._prepare_path_drawer(renderer) as draw_path: |
| 546 | + path = self.get_path() |
| 547 | + transform = self.get_transform() |
| 548 | + tpath = transform.transform_path_non_affine(path) |
| 549 | + affine = transform.get_affine() |
| 550 | + draw_path(tpath, affine, |
| 551 | + # Work around a bug in the PDF and SVG renderers, which |
| 552 | + # do not draw the hatches if the facecolor is fully |
| 553 | + # transparent, but do if it is None. |
| 554 | + self._facecolor if self._facecolor[3] else None) |
| 555 | + |
539 | 556 | def get_path(self):
|
540 | 557 | """
|
541 | 558 | Return the path of this patch
|
@@ -4256,67 +4273,23 @@ def draw(self, renderer):
|
4256 | 4273 | if not self.get_visible():
|
4257 | 4274 | return
|
4258 | 4275 |
|
4259 |
| - renderer.open_group('patch', self.get_gid()) |
4260 |
| - gc = renderer.new_gc() |
4261 |
| - |
4262 |
| - gc.set_foreground(self._edgecolor, isRGBA=True) |
4263 |
| - |
4264 |
| - lw = self._linewidth |
4265 |
| - if self._edgecolor[3] == 0: |
4266 |
| - lw = 0 |
4267 |
| - gc.set_linewidth(lw) |
4268 |
| - gc.set_dashes(self._dashoffset, self._dashes) |
4269 |
| - |
4270 |
| - gc.set_antialiased(self._antialiased) |
4271 |
| - self._set_gc_clip(gc) |
4272 |
| - gc.set_capstyle('round') |
4273 |
| - gc.set_snap(self.get_snap()) |
4274 |
| - |
4275 |
| - rgbFace = self._facecolor |
4276 |
| - if rgbFace[3] == 0: |
4277 |
| - rgbFace = None # (some?) renderers expect this as no-fill signal |
4278 |
| - |
4279 |
| - gc.set_alpha(self._alpha) |
4280 |
| - |
4281 |
| - if self._hatch: |
4282 |
| - gc.set_hatch(self._hatch) |
4283 |
| - if self._hatch_color is not None: |
4284 |
| - try: |
4285 |
| - gc.set_hatch_color(self._hatch_color) |
4286 |
| - except AttributeError: |
4287 |
| - # if we end up with a GC that does not have this method |
4288 |
| - warnings.warn("Your backend does not support setting the " |
4289 |
| - "hatch color.") |
4290 |
| - |
4291 |
| - if self.get_sketch_params() is not None: |
4292 |
| - gc.set_sketch_params(*self.get_sketch_params()) |
| 4276 | + # FancyArrowPatch have traditionally forced the capstyle and joinstyle. |
| 4277 | + with cbook._setattr_cm(self, _capstyle='round', _joinstyle='round'), \ |
| 4278 | + self._prepare_path_drawer(renderer) as draw_path: |
4293 | 4279 |
|
4294 |
| - # FIXME : dpi_cor is for the dpi-dependecy of the |
4295 |
| - # linewidth. There could be room for improvement. |
4296 |
| - # |
4297 |
| - # dpi_cor = renderer.points_to_pixels(1.) |
4298 |
| - self.set_dpi_cor(renderer.points_to_pixels(1.)) |
4299 |
| - path, fillable = self.get_path_in_displaycoord() |
| 4280 | + # FIXME : dpi_cor is for the dpi-dependecy of the linewidth. There |
| 4281 | + # could be room for improvement. |
| 4282 | + self.set_dpi_cor(renderer.points_to_pixels(1.)) |
| 4283 | + path, fillable = self.get_path_in_displaycoord() |
4300 | 4284 |
|
4301 |
| - if not cbook.iterable(fillable): |
4302 |
| - path = [path] |
4303 |
| - fillable = [fillable] |
| 4285 | + if not cbook.iterable(fillable): |
| 4286 | + path = [path] |
| 4287 | + fillable = [fillable] |
4304 | 4288 |
|
4305 |
| - affine = transforms.IdentityTransform() |
| 4289 | + affine = transforms.IdentityTransform() |
4306 | 4290 |
|
4307 |
| - if self.get_path_effects(): |
4308 |
| - from matplotlib.patheffects import PathEffectRenderer |
4309 |
| - renderer = PathEffectRenderer(self.get_path_effects(), renderer) |
4310 |
| - |
4311 |
| - for p, f in zip(path, fillable): |
4312 |
| - if f: |
4313 |
| - renderer.draw_path(gc, p, affine, rgbFace) |
4314 |
| - else: |
4315 |
| - renderer.draw_path(gc, p, affine, None) |
4316 |
| - |
4317 |
| - gc.restore() |
4318 |
| - renderer.close_group('patch') |
4319 |
| - self.stale = False |
| 4291 | + for p, f in zip(path, fillable): |
| 4292 | + draw_path(p, affine, self._facecolor if f else None) |
4320 | 4293 |
|
4321 | 4294 |
|
4322 | 4295 | class ConnectionPatch(FancyArrowPatch):
|
|
0 commit comments