1+ import contextlib
12import functools
23import math
34from numbers import Number
@@ -481,11 +482,16 @@ def get_hatch(self):
481482 'Return the current hatching pattern'
482483 return self ._hatch
483484
484- @artist .allow_rasterization
485- def draw (self , renderer ):
486- 'Draw the :class:`Patch` to the given *renderer*.'
487- if not self .get_visible ():
488- return
485+ @contextlib .contextmanager
486+ def _bind_draw_path_function (self , renderer ):
487+ """
488+ ``draw()`` helper factored out for sharing with `FancyArrowPatch`.
489+
490+ Yields a callable ``dp`` such that calling ``dp(*args, **kwargs)`` is
491+ equivalent to calling ``renderer1.draw_path(gc, *args, **kwargs)``
492+ where ``renderer1`` and ``gc`` have been suitably set from ``renderer``
493+ and the artist's properties.
494+ """
489495
490496 renderer .open_group ('patch' , self .get_gid ())
491497 gc = renderer .new_gc ()
@@ -496,7 +502,7 @@ def draw(self, renderer):
496502 if self ._edgecolor [3 ] == 0 :
497503 lw = 0
498504 gc .set_linewidth (lw )
499- gc .set_dashes (0 , self ._dashes )
505+ gc .set_dashes (self . _dashoffset , self ._dashes )
500506 gc .set_capstyle (self ._capstyle )
501507 gc .set_joinstyle (self ._joinstyle )
502508
@@ -525,21 +531,39 @@ def draw(self, renderer):
525531 if self .get_sketch_params () is not None :
526532 gc .set_sketch_params (* self .get_sketch_params ())
527533
528- path = self .get_path ()
529- transform = self .get_transform ()
530- tpath = transform .transform_path_non_affine (path )
531- affine = transform .get_affine ()
532-
533534 if self .get_path_effects ():
534535 from matplotlib .patheffects import PathEffectRenderer
535536 renderer = PathEffectRenderer (self .get_path_effects (), renderer )
536537
537- renderer .draw_path (gc , tpath , affine , rgbFace )
538+ # In `with _bind_draw_path_function(renderer) as draw_path: ...`
539+ # (in the implementations of `draw()` below), calls to `draw_path(...)`
540+ # will occur as if they took place here with `gc` inserted as
541+ # additional first argument.
542+ yield functools .partial (renderer .draw_path , gc )
538543
539544 gc .restore ()
540545 renderer .close_group ('patch' )
541546 self .stale = False
542547
548+ @artist .allow_rasterization
549+ def draw (self , renderer ):
550+ 'Draw the :class:`Patch` to the given *renderer*.'
551+ if not self .get_visible ():
552+ return
553+
554+ # Patch has traditionally ignored the dashoffset.
555+ with cbook ._setattr_cm (self , _dashoffset = 0 ), \
556+ self ._bind_draw_path_function (renderer ) as draw_path :
557+ path = self .get_path ()
558+ transform = self .get_transform ()
559+ tpath = transform .transform_path_non_affine (path )
560+ affine = transform .get_affine ()
561+ draw_path (tpath , affine ,
562+ # Work around a bug in the PDF and SVG renderers, which
563+ # do not draw the hatches if the facecolor is fully
564+ # transparent, but do if it is None.
565+ self ._facecolor if self ._facecolor [3 ] else None )
566+
543567 def get_path (self ):
544568 """
545569 Return the path of this patch
@@ -4263,69 +4287,25 @@ def draw(self, renderer):
42634287 if not self .get_visible ():
42644288 return
42654289
4266- renderer .open_group ('patch' , self .get_gid ())
4267- gc = renderer .new_gc ()
4268-
4269- gc .set_foreground (self ._edgecolor , isRGBA = True )
4270-
4271- lw = self ._linewidth
4272- if self ._edgecolor [3 ] == 0 :
4273- lw = 0
4274- gc .set_linewidth (lw )
4275- gc .set_dashes (self ._dashoffset , self ._dashes )
4276-
4277- gc .set_antialiased (self ._antialiased )
4278- self ._set_gc_clip (gc )
4279- gc .set_capstyle ('round' )
4280- gc .set_snap (self .get_snap ())
4290+ # FancyArrowPatch has traditionally forced the capstyle and joinstyle.
4291+ with cbook ._setattr_cm (self , _capstyle = 'round' , _joinstyle = 'round' ), \
4292+ self ._bind_draw_path_function (renderer ) as draw_path :
42814293
4282- rgbFace = self ._facecolor
4283- if rgbFace [3 ] == 0 :
4284- rgbFace = None # (some?) renderers expect this as no-fill signal
4294+ # FIXME : dpi_cor is for the dpi-dependecy of the linewidth. There
4295+ # could be room for improvement.
4296+ self .set_dpi_cor (renderer .points_to_pixels (1. ))
4297+ path , fillable = self .get_path_in_displaycoord ()
42854298
4286- gc .set_alpha (self ._alpha )
4299+ if not cbook .iterable (fillable ):
4300+ path = [path ]
4301+ fillable = [fillable ]
42874302
4288- if self ._hatch :
4289- gc .set_hatch (self ._hatch )
4290- if self ._hatch_color is not None :
4291- try :
4292- gc .set_hatch_color (self ._hatch_color )
4293- except AttributeError :
4294- # if we end up with a GC that does not have this method
4295- cbook .warn_deprecated (
4296- "3.1" , "Your backend does not support setting the "
4297- "hatch color; such backends will become unsupported "
4298- "in Matplotlib 3.3." )
4303+ affine = transforms .IdentityTransform ()
42994304
4300- if self .get_sketch_params () is not None :
4301- gc .set_sketch_params (* self .get_sketch_params ())
4302-
4303- # FIXME : dpi_cor is for the dpi-dependecy of the
4304- # linewidth. There could be room for improvement.
4305- #
4306- # dpi_cor = renderer.points_to_pixels(1.)
4307- self .set_dpi_cor (renderer .points_to_pixels (1. ))
4308- path , fillable = self .get_path_in_displaycoord ()
4309-
4310- if not cbook .iterable (fillable ):
4311- path = [path ]
4312- fillable = [fillable ]
4313-
4314- affine = transforms .IdentityTransform ()
4315-
4316- if self .get_path_effects ():
4317- from matplotlib .patheffects import PathEffectRenderer
4318- renderer = PathEffectRenderer (self .get_path_effects (), renderer )
4319-
4320- for p , f in zip (path , fillable ):
4321- if f :
4322- renderer .draw_path (gc , p , affine , rgbFace )
4323- else :
4324- renderer .draw_path (gc , p , affine , None )
4325-
4326- gc .restore ()
4327- renderer .close_group ('patch' )
4328- self .stale = False
4305+ for p , f in zip (path , fillable ):
4306+ draw_path (
4307+ p , affine ,
4308+ self ._facecolor if f and self ._facecolor [3 ] else None )
43294309
43304310
43314311class ConnectionPatch (FancyArrowPatch ):
0 commit comments