GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix the unintended blending of fill/hatch/stroke when drawing patches by ayshih · Pull Request #32343 · matplotlib/matplotlib

Conversation

@ayshih

@ayshih ayshih commented Sep 12, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ayshih ayshih added this to the v3.12.0 milestone Sep 12, 2026
@github-actions github-actions Bot added backend: pgf backend: agg backend: cairo labels 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
@ayshih
ayshih force-pushed the patch_blending branch from 8abe2c2 to 3cd26de Compare September 13, 2026 12:23
iccir
iccir approved these changes Sep 13, 2026
View reviewed changes

@iccir iccir left a comment

Copy link
Copy Markdown
Contributor

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread lib/matplotlib/backends/backend_pgf.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ayshih
ayshih force-pushed the patch_blending branch from 3cd26de to 1cf904d Compare September 13, 2026 22:33
iccir
iccir approved these changes Sep 14, 2026
View reviewed changes
Comment thread lib/matplotlib/backends/backend_pgf.py Outdated

@iccir iccir Sep 14, 2026

Copy link
Copy Markdown
Contributor

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.

Since you are now specifying stroke and fill in every call, should the default values be removed? I find the defaults of True/False to be a bit confusing.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ayshih ayshih Sep 14, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

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.

Ah, good idea! I did in fact get tripped up by those weird defaults when writing this PR. I have now made them keyword-only with no defaults.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ayshih
ayshih force-pushed the patch_blending branch from 1cf904d to 57c3f28 Compare September 14, 2026 13:13
tacaswell
tacaswell approved these changes Oct 8, 2026
View reviewed changes

@tacaswell tacaswell left a comment

Copy link
Copy Markdown
Member

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.

@ayshih can self-merge when CI is green.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
ayshih added 5 commits October 8, 2026 15:32
@ayshih
Fix Agg bug of internally blending fill/hatch/stroke of paths
8449128
@ayshih
Fix Cairo bug of internally blending fill/hatch/stroke of paths
e4d8a5c
@ayshih
Fix PGF bugs related to hatch styles and hatch priority
9f78df3
@ayshih
Fix PGF bug of internally blending fill/hatch/stroke of paths
123f409
@ayshih
Add figure tests to check for internal blending of fill/hatch/stroke
ad560b8
@ayshih
ayshih force-pushed the patch_blending branch from 57c3f28 to ad560b8 Compare October 8, 2026 19:33
@ayshih
ayshih merged commit 0a1451c into matplotlib:main Oct 9, 2026
42 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@ayshih
ayshih deleted the patch_blending branch October 9, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@tacaswell tacaswell tacaswell approved these changes
@iccir iccir iccir approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

backend: agg backend: cairo backend: pgf

Projects

None yet

Milestone

v3.12.0

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@ayshih @tacaswell @iccir
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.