-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Factor out common code between Patch.draw and FancyArrowPatch.draw. #11741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import contextlib | ||
import functools | ||
import math | ||
from numbers import Number | ||
|
@@ -481,11 +482,16 @@ def get_hatch(self): | |
'Return the current hatching pattern' | ||
return self._hatch | ||
|
||
@artist.allow_rasterization | ||
def draw(self, renderer): | ||
'Draw the :class:`Patch` to the given *renderer*.' | ||
if not self.get_visible(): | ||
return | ||
@contextlib.contextmanager | ||
def _bind_draw_path_function(self, renderer): | ||
""" | ||
``draw()`` helper factored out for sharing with `FancyArrowPatch`. | ||
|
||
Yields a callable ``dp`` such that calling ``dp(*args, **kwargs)`` is | ||
equivalent to calling ``renderer1.draw_path(gc, *args, **kwargs)`` | ||
where ``renderer1`` and ``gc`` have been suitably set from ``renderer`` | ||
and the artist's properties. | ||
""" | ||
|
||
renderer.open_group('patch', self.get_gid()) | ||
gc = renderer.new_gc() | ||
|
@@ -496,7 +502,7 @@ def draw(self, renderer): | |
if self._edgecolor[3] == 0: | ||
lw = 0 | ||
gc.set_linewidth(lw) | ||
gc.set_dashes(0, self._dashes) | ||
gc.set_dashes(self._dashoffset, self._dashes) | ||
gc.set_capstyle(self._capstyle) | ||
gc.set_joinstyle(self._joinstyle) | ||
|
||
|
@@ -525,21 +531,39 @@ def draw(self, renderer): | |
if self.get_sketch_params() is not None: | ||
gc.set_sketch_params(*self.get_sketch_params()) | ||
|
||
path = self.get_path() | ||
transform = self.get_transform() | ||
tpath = transform.transform_path_non_affine(path) | ||
affine = transform.get_affine() | ||
|
||
if self.get_path_effects(): | ||
from matplotlib.patheffects import PathEffectRenderer | ||
renderer = PathEffectRenderer(self.get_path_effects(), renderer) | ||
|
||
renderer.draw_path(gc, tpath, affine, rgbFace) | ||
# In `with _bind_draw_path_function(renderer) as draw_path: ...` | ||
# (in the implementations of `draw()` below), calls to `draw_path(...)` | ||
# will occur as if they took place here with `gc` inserted as | ||
# additional first argument. | ||
yield functools.partial(renderer.draw_path, gc) | ||
|
||
gc.restore() | ||
renderer.close_group('patch') | ||
self.stale = False | ||
|
||
@artist.allow_rasterization | ||
def draw(self, renderer): | ||
'Draw the :class:`Patch` to the given *renderer*.' | ||
if not self.get_visible(): | ||
return | ||
|
||
# Patch has traditionally ignored the dashoffset. | ||
with cbook._setattr_cm(self, _dashoffset=0), \ | ||
self._bind_draw_path_function(renderer) as draw_path: | ||
path = self.get_path() | ||
transform = self.get_transform() | ||
tpath = transform.transform_path_non_affine(path) | ||
affine = transform.get_affine() | ||
draw_path(tpath, affine, | ||
# Work around a bug in the PDF and SVG renderers, which | ||
# do not draw the hatches if the facecolor is fully | ||
# transparent, but do if it is None. | ||
self._facecolor if self._facecolor[3] else None) | ||
|
||
def get_path(self): | ||
""" | ||
Return the path of this patch | ||
|
@@ -4263,69 +4287,25 @@ def draw(self, renderer): | |
if not self.get_visible(): | ||
return | ||
|
||
renderer.open_group('patch', self.get_gid()) | ||
gc = renderer.new_gc() | ||
|
||
gc.set_foreground(self._edgecolor, isRGBA=True) | ||
|
||
lw = self._linewidth | ||
if self._edgecolor[3] == 0: | ||
lw = 0 | ||
gc.set_linewidth(lw) | ||
gc.set_dashes(self._dashoffset, self._dashes) | ||
|
||
gc.set_antialiased(self._antialiased) | ||
self._set_gc_clip(gc) | ||
gc.set_capstyle('round') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The context uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forced it to "round" above (in the setattr_cm). Yes, ignoring the capstyle was probably a long-standing bug (the kind of things that such refactors uncover...) but changing that would result in changes in the baseline images (... that's how I realized the discrepancy). I'll leave this as it is until someone actually complains or we have some othe reason to change the baseline images. |
||
gc.set_snap(self.get_snap()) | ||
# FancyArrowPatch has traditionally forced the capstyle and joinstyle. | ||
with cbook._setattr_cm(self, _capstyle='round', _joinstyle='round'), \ | ||
self._bind_draw_path_function(renderer) as draw_path: | ||
|
||
rgbFace = self._facecolor | ||
if rgbFace[3] == 0: | ||
rgbFace = None # (some?) renderers expect this as no-fill signal | ||
# FIXME : dpi_cor is for the dpi-dependecy of the linewidth. There | ||
# could be room for improvement. | ||
self.set_dpi_cor(renderer.points_to_pixels(1.)) | ||
path, fillable = self.get_path_in_displaycoord() | ||
|
||
gc.set_alpha(self._alpha) | ||
if not cbook.iterable(fillable): | ||
path = [path] | ||
fillable = [fillable] | ||
|
||
if self._hatch: | ||
gc.set_hatch(self._hatch) | ||
if self._hatch_color is not None: | ||
try: | ||
gc.set_hatch_color(self._hatch_color) | ||
except AttributeError: | ||
# if we end up with a GC that does not have this method | ||
cbook.warn_deprecated( | ||
"3.1", "Your backend does not support setting the " | ||
"hatch color; such backends will become unsupported " | ||
"in Matplotlib 3.3.") | ||
affine = transforms.IdentityTransform() | ||
|
||
if self.get_sketch_params() is not None: | ||
gc.set_sketch_params(*self.get_sketch_params()) | ||
|
||
# FIXME : dpi_cor is for the dpi-dependecy of the | ||
# linewidth. There could be room for improvement. | ||
# | ||
# dpi_cor = renderer.points_to_pixels(1.) | ||
self.set_dpi_cor(renderer.points_to_pixels(1.)) | ||
path, fillable = self.get_path_in_displaycoord() | ||
|
||
if not cbook.iterable(fillable): | ||
path = [path] | ||
fillable = [fillable] | ||
|
||
affine = transforms.IdentityTransform() | ||
|
||
if self.get_path_effects(): | ||
from matplotlib.patheffects import PathEffectRenderer | ||
renderer = PathEffectRenderer(self.get_path_effects(), renderer) | ||
|
||
for p, f in zip(path, fillable): | ||
if f: | ||
renderer.draw_path(gc, p, affine, rgbFace) | ||
else: | ||
renderer.draw_path(gc, p, affine, None) | ||
|
||
gc.restore() | ||
renderer.close_group('patch') | ||
self.stale = False | ||
for p, f in zip(path, fillable): | ||
draw_path( | ||
p, affine, | ||
self._facecolor if f and self._facecolor[3] else None) | ||
|
||
|
||
class ConnectionPatch(FancyArrowPatch): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The context uses
gc.set_dashes(0, self._dashes)
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I had missed that. I restored the old behavior using setattr_cm (in Patch.draw), leaving a comment similar to the one for the capstyle in FancyArrowPatch.