@@ -1541,6 +1541,17 @@ def hatchPattern(self, hatch_style):
1541
1541
face = tuple (face )
1542
1542
hatch_style = (edge , face , hatch , lw )
1543
1543
1544
+ if isinstance (hatch , list ):
1545
+ hatch_tuple = tuple (tuple (h .items ()) for h in hatch )
1546
+ hatch_style = (edge , face , hatch_tuple , lw )
1547
+ pattern = self ._hatch_patterns .get (hatch_style , None )
1548
+ if pattern is not None :
1549
+ return pattern
1550
+
1551
+ name = next (self ._hatch_pattern_seq )
1552
+ self ._hatch_patterns [hatch_style ] = name
1553
+ return name
1554
+
1544
1555
pattern = self ._hatch_patterns .get (hatch_style , None )
1545
1556
if pattern is not None :
1546
1557
return pattern
@@ -1557,6 +1568,18 @@ def writeHatches(self):
1557
1568
hatchDict = dict ()
1558
1569
sidelen = 72.0
1559
1570
for hatch_style , name in self ._hatch_patterns .items ():
1571
+ stroke_rgb , fill_rgb , hatch , lw = hatch_style
1572
+ filled = True
1573
+ if isinstance (hatch , tuple ):
1574
+ custom_hatch = [dict (h ) for h in hatch ]
1575
+ hatch_buffer_scale = custom_hatch [0 ].get ('hatch_buffer_scale' , 1.0 )
1576
+ sidelen = 72.0 * hatch_buffer_scale
1577
+ path = Path .hatchstyle (custom_hatch )
1578
+ else :
1579
+ sidelen = 72.0
1580
+ path = Path .hatch (hatch )
1581
+ filled = filled and all (h not in '|-/\\ +xX' for h in hatch )
1582
+
1560
1583
ob = self .reserveObject ('hatch pattern' )
1561
1584
hatchDict [name ] = ob
1562
1585
res = {'Procsets' :
@@ -1571,7 +1594,6 @@ def writeHatches(self):
1571
1594
# Change origin to match Agg at top-left.
1572
1595
'Matrix' : [1 , 0 , 0 , 1 , 0 , self .height * 72 ]})
1573
1596
1574
- stroke_rgb , fill_rgb , hatch , lw = hatch_style
1575
1597
self .output (stroke_rgb [0 ], stroke_rgb [1 ], stroke_rgb [2 ],
1576
1598
Op .setrgb_stroke )
1577
1599
if fill_rgb is not None :
@@ -1583,9 +1605,12 @@ def writeHatches(self):
1583
1605
self .output (lw , Op .setlinewidth )
1584
1606
1585
1607
self .output (* self .pathOperations (
1586
- Path . hatch ( hatch ) ,
1608
+ path ,
1587
1609
Affine2D ().scale (sidelen ),
1588
1610
simplify = False ))
1611
+ if filled :
1612
+ self .output (stroke_rgb [0 ], stroke_rgb [1 ], stroke_rgb [2 ],
1613
+ Op .setrgb_nonstroke )
1589
1614
self .output (Op .fill_stroke )
1590
1615
1591
1616
self .endStream ()
@@ -1954,6 +1979,9 @@ def __init__(self, file, image_dpi, height, width):
1954
1979
self .file = file
1955
1980
self .gc = self .new_gc ()
1956
1981
self .image_dpi = image_dpi
1982
+ self .hatch_buffer_scale = (
1983
+ (max (self .width , self .height )) if RendererPdf .hatchstyles_enabled else 1.0
1984
+ )
1957
1985
1958
1986
def finalize (self ):
1959
1987
self .file .output (* self .gc .finalize ())
@@ -2020,6 +2048,7 @@ def draw_image(self, gc, x, y, im, transform=None):
2020
2048
2021
2049
def draw_path (self , gc , path , transform , rgbFace = None ):
2022
2050
# docstring inherited
2051
+ gc .set_hatch_buffer_scale (self .hatch_buffer_scale )
2023
2052
self .check_gc (gc , rgbFace )
2024
2053
self .file .writePath (
2025
2054
path , transform ,
@@ -2511,13 +2540,20 @@ def alpha_cmd(self, alpha, forced, effective_alphas):
2511
2540
name = self .file .alphaState (effective_alphas )
2512
2541
return [name , Op .setgstate ]
2513
2542
2514
- def hatch_cmd (self , hatch , hatch_color , hatch_linewidth ):
2515
- if not hatch :
2543
+ def hatch_cmd (self , hatch , hatch_color , hatch_linewidth , custom_hatch ):
2544
+ if not ( hatch or len ( custom_hatch )) :
2516
2545
if self ._fillcolor is not None :
2517
2546
return self .fillcolor_cmd (self ._fillcolor )
2518
2547
else :
2519
2548
return [Name ('DeviceRGB' ), Op .setcolorspace_nonstroke ]
2520
2549
else :
2550
+ if len (custom_hatch ):
2551
+ hatch_style = (hatch_color , self ._fillcolor ,
2552
+ custom_hatch , hatch_linewidth )
2553
+ name = self .file .hatchPattern (hatch_style )
2554
+ return [Name ('Pattern' ), Op .setcolorspace_nonstroke ,
2555
+ name , Op .setcolor_nonstroke ]
2556
+
2521
2557
hatch_style = (hatch_color , self ._fillcolor , hatch , hatch_linewidth )
2522
2558
name = self .file .hatchPattern (hatch_style )
2523
2559
return [Name ('Pattern' ), Op .setcolorspace_nonstroke ,
@@ -2583,7 +2619,7 @@ def clip_cmd(self, cliprect, clippath):
2583
2619
(('_dashes' ,), dash_cmd ),
2584
2620
(('_rgb' ,), rgb_cmd ),
2585
2621
# must come after fillcolor and rgb
2586
- (('_hatch' , '_hatch_color' , '_hatch_linewidth' ), hatch_cmd ),
2622
+ (('_hatch' , '_hatch_color' , '_hatch_linewidth' , '_hatchstyle' ), hatch_cmd ),
2587
2623
)
2588
2624
2589
2625
def delta (self , other ):
0 commit comments