Skip to content

Commit 3c1da25

Browse files
committed
Fix Agg/Cairo pcolor/pcolormesh by using an isolated blend group
1 parent b900140 commit 3c1da25

6 files changed

Lines changed: 55 additions & 0 deletions

File tree

‎lib/matplotlib/backend_bases.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def __init__(self):
159159
self._rasterizing = False
160160

161161
self._use_blend_group_for_contourf = False
162+
self._use_blend_group_for_pcolor = False
162163

163164
def open_group(self, s, gid=None):
164165
"""

‎lib/matplotlib/backends/backend_agg.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def __init__(self, width, height, dpi):
8686
self._override_blend_mode_to_knockout = False
8787

8888
self._use_blend_group_for_contourf = True
89+
self._use_blend_group_for_pcolor = True
8990

9091
self._update_methods()
9192
self.mathtext_parser = MathTextParser('path')

‎lib/matplotlib/backends/backend_cairo.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ def __init__(self, dpi):
105105
self._override_blend_mode_to_knockout = False
106106

107107
self._use_blend_group_for_contourf = True
108+
self._use_blend_group_for_pcolor = True
108109

109110
def set_context(self, ctx):
110111
surface = ctx.get_target()

‎lib/matplotlib/collections.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2546,6 +2546,7 @@ def draw(self, renderer):
25462546
if not self.get_visible():
25472547
return
25482548
renderer.open_group(self.__class__.__name__, self.get_gid())
2549+
25492550
transform = self.get_transform()
25502551
offset_trf = self.get_offset_transform()
25512552
offsets = self.get_offsets()
@@ -2580,14 +2581,24 @@ def draw(self, renderer):
25802581
renderer.draw_gouraud_triangles(
25812582
gc, triangles, colors, transform.frozen())
25822583
else:
2584+
isolate = (renderer._use_blend_group_for_pcolor and self._antialiased
2585+
and (self._edgecolors.size == 0 or self._edgecolors[0][3] == 0))
2586+
if isolate:
2587+
gc.set_blend_mode("plus")
2588+
renderer.open_blend_group(self.get_blend_mode())
2589+
25832590
renderer.draw_quad_mesh(
25842591
gc, transform.frozen(),
25852592
coordinates.shape[1] - 1, coordinates.shape[0] - 1,
25862593
coordinates, offsets, offset_trf,
25872594
# Backends expect flattened rgba arrays (n*m, 4) for fc and ec
25882595
self.get_facecolor().reshape((-1, 4)),
25892596
self._antialiased, self.get_edgecolors().reshape((-1, 4)))
2597+
2598+
if isolate:
2599+
renderer.close_blend_group()
25902600
gc.restore()
2601+
25912602
renderer.close_group(self.__class__.__name__)
25922603
self.stale = False
25932604

@@ -2688,6 +2699,21 @@ def get_edgecolor(self):
26882699
return ec
26892700
return ec[unmasked_polys, :]
26902701

2702+
@artist.allow_rasterization
2703+
def draw(self, renderer):
2704+
isolate = (renderer._use_blend_group_for_pcolor and np.all(self._antialiaseds)
2705+
and (self._edgecolors.size == 0 or self._edgecolors[0][3] == 0))
2706+
if isolate:
2707+
blend_mode = self.get_blend_mode()
2708+
self.set_blend_mode("plus")
2709+
renderer.open_blend_group(blend_mode)
2710+
2711+
super().draw(renderer)
2712+
2713+
if isolate:
2714+
renderer.close_blend_group()
2715+
self.set_blend_mode(blend_mode)
2716+
26912717
def get_facecolor(self):
26922718
# docstring inherited
26932719
# We only want to return the facecolors of the polygons
19.6 KB
Loading

‎lib/matplotlib/tests/test_axes.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,32 @@ def test_pcolormesh_alpha():
15071507
ax4.pcolormesh(Qx, Qy, Z, cmap=cmap, shading='gouraud', zorder=1)
15081508

15091509

1510+
@image_comparison(['pcolormesh_antialiasing.png'], style='mpl20')
1511+
def test_pcolormesh_antialiasing():
1512+
N = 5
1513+
data = np.arange(N**2, dtype=float).reshape((N, N))
1514+
data[2, 2] = np.nan
1515+
1516+
x, y = np.meshgrid(np.arange(N + 1), np.arange(N + 1))
1517+
1518+
rotation = mtransforms.Affine2D().rotate(1)
1519+
1520+
fig, axs = plt.subplots(2, 3, figsize=(5, 3.5), layout="constrained")
1521+
1522+
for i, antialiased in enumerate([None, False, True]):
1523+
kwargs = {'cmap': 'jet', 'alpha': 0.5}
1524+
if antialiased is not None:
1525+
kwargs['antialiased'] = antialiased
1526+
1527+
axs[0, i].pcolormesh(x, y, data, transform=rotation + axs[0, i].transData,
1528+
**kwargs)
1529+
axs[1, i].pcolor(x, y, data, transform=rotation + axs[1, i].transData, **kwargs)
1530+
1531+
for j in range(2):
1532+
axs[j, i].set_aspect("equal")
1533+
axs[j, i].set_axis_off()
1534+
1535+
15101536
@pytest.mark.parametrize("dims,alpha", [(3, 1), (4, 0.5)])
15111537
@check_figures_equal()
15121538
def test_pcolormesh_rgba(fig_test, fig_ref, dims, alpha):

0 commit comments

Comments
 (0)