Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix the unintended blending of fill/hatch/stroke when drawing patches - #32343

Open
ayshih wants to merge 5 commits into
matplotlib:mainfrom
ayshih:patch_blending
Open

Fix the unintended blending of fill/hatch/stroke when drawing patches#32343
ayshih wants to merge 5 commits into
matplotlib:mainfrom
ayshih:patch_blending

Conversation

@ayshih

@ayshih ayshih commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

PR summary

This PR fixes a bug in the Agg/Cairo/PGF backends where applying a non-"normal" blend mode to a patch unintentionally resulted in blending the fill/hatch/stroke with each other using that same blend mode. Instead, the correct behavior – which the PDF/SVG backends already do – is for the fill/hatch/stroke to always be blended with each other using the "normal" blend mode, and then the result is blended with the backdrop using the non-"normal" blend mode. This PR makes the Agg/Cairo/PGF backends match the PDF/SVG backends.

The changes to the Cairo/PGF backends are straightforward because we can use open_blend_group()/close_blend_group() to create an isolated blend group for the fill/hatch/stroke. The blend group is used only if an non-"normal" blend mode is specified and if more than one of fill/hatch/stroke is involved. (If there is only one of fill/hatch/stroke, no unintended blending can happen.) The changes to the Agg backend are a little trickier since the drawing function is at a deeper code layer than those renderer methods, so we have to mimic an isolated blend group by manually swapping a fresh buffer in and out of the C++ renderer.

Since this PR is related to blend modes (#31162), it is not to be backported.

In the plots below, the first row is "normal" blend mode, and the second row is "multiply" blend mode. Note how in the "before this PR" image, the part of the stroke that overlaps the fill is being "multiply" blended instead of "normal" blended, and the star hatching plus fill is a different color even over the white backdrop because the stars are getting "multiply" blended with the fill.

Before this PR

before

After this PR

after

Generating code

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

data = np.arange(35).reshape((7, 5)) % 7

fc_list = ['none', 'none', 'none', 'none', 'm', 'm', 'm', 'm']
ec_list = ['none', 'c', 'none', 'c', 'none', 'c', 'none', 'c']
lw_list = [0, 5, 0, 5, 0, 5, 0, 5]
hatch_list = [None, None, '*', '*', None, None, '*', '*']
hatchcolor_list = [None, None, 'y', 'y', None, None, 'y', 'y']

fig, axs = plt.subplots(2, 8, figsize=(8, 2), layout='constrained')

for i, blend_mode in enumerate(['normal', 'multiply']):
    for ax, fc, ec, lw, hatch, hatchcolor in zip(axs[i, :], fc_list, ec_list, lw_list,
                                                 hatch_list, hatchcolor_list):
        ax.imshow(data, cmap='jet')

        circle = Circle((3, 3), 3, fc=fc, ec=ec, lw=lw,
                        hatch=hatch, hatchcolor=hatchcolor, blend_mode=blend_mode)
        ax.add_patch(circle)

        ax.autoscale_view()
        ax.set_axis_off()

plt.show()

AI Disclosure

No AI was used

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • [N/A] Plotting related features are demonstrated in an example
  • [N/A] New features and API changes have release notes
  • [N/A] Documentation complies with general and docstring guidelines

@ayshih ayshih added this to the v3.12.0 milestone Sep 12, 2026
@ayshih
ayshih force-pushed the patch_blending branch 6 times, most recently from 35e707b to 362656e Compare September 12, 2026 16:02
@ayshih
ayshih marked this pull request as ready for review September 13, 2026 05:01

@iccir iccir left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. I'm a bit uneasy with the PGF format/backend, so others may want to examine that in more detail.

Comment thread lib/matplotlib/backends/backend_pgf.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants