Skip to content

SVG: simplify large filled paths e.g. fill_between (#22803)#31796

Closed
evanscastonguay wants to merge 1 commit into
matplotlib:mainfrom
evanscastonguay:prototype-3knob
Closed

SVG: simplify large filled paths e.g. fill_between (#22803)#31796
evanscastonguay wants to merge 1 commit into
matplotlib:mainfrom
evanscastonguay:prototype-3knob

Conversation

@evanscastonguay

@evanscastonguay evanscastonguay commented May 31, 2026

Copy link
Copy Markdown

Closes #22803.

The problem

fill_between writes a very large SVG — ~1 MB for a plot whose equivalent line version is ~400 KB.

Why (first principles)

A vector file should carry only the geometry needed to render it. matplotlib already strips sub-pixel-redundant points from line plots via path simplification — but the polygon produced by fill_between is written verbatim, because the SVG backend hardcodes simplify=False where it emits filled / cached paths. So tens of thousands of invisible, redundant vertices end up in the file.

The fix

Let the SVG backend simplify large paths — including filled ones — exactly as it already does for strokes: honor path.should_simplify (plus a vertex-count threshold for closed fills, which should_simplify excludes), respect rcParams["path.simplify"], and leave hatched paths exact. SVG backend only — agg/pdf rendering is untouched.

Proof it fixes the issue

On the issue's reproduction:

before after
fill_between SVG 1012 KB 407 KB (~2.4×)
fill-path vertices 40,003 16,504
rasterized? no no — stays vector
render-resolution pixels identical (the dropped vertices were sub-pixel)

Testing

  • agg + pdf are byte-for-byte unchanged (the change is SVG-only). Full local sweep of the path/patch/collection/simplification/contour/colorbar/SVG-backend modules: 495 passed, 0 failed, incl. imshow_clip, arc_ellipse, contour_colorbar.
  • New regression test test_fill_between_svg_simplified asserts the fill path is simplified and stays vector.
  • SVG image comparisons (run locally with Inkscape): 107 pass; 4 baselines shift, all small and benign (sub-pixel edge drift, confirmed via diff images): arc_ellipse (RMS 0.010), test_log_locator_levels (0.476), contour_colorbar (0.642), test_set_line_coll_dash_image (1.616).

The one decision for maintainers

Because this is SVG-only, those 4 plots' SVG output now differs slightly from their (agg-based) baselines — the expected consequence of an intended rendering change. Two clean ways to resolve, your call:

  • (a) refresh / set a small documented tolerance for those 4 SVG baselines (surgical), or
  • (b) apply simplification across backends for consistency (all formats match, but more baselines change).

I've proposed (a) as the lighter option and can push either. Marked draft pending that decision.

@timhoffm

timhoffm commented May 31, 2026

Copy link
Copy Markdown
Member

The PR text looks completely AI generated and does not use our PR template. This does not instill trust any human oversight was put into this.

Please fill in all information from the PR template and make sure to comply with our AI policy.

@timhoffm timhoffm added the status: autoclose candidate PRs that are not yet ready for review and may be automatically closed in two weeks label May 31, 2026
@github-actions

Copy link
Copy Markdown

⏰ This pull request might be automatically closed in two weeks from now.

Thank you for your contribution to Matplotlib and for the effort you have put into this PR. This pull request does not yet meet the quality and clarity standards needed for an effective review. Project maintainers have limited time for code reviews, and our goal is to prioritize well-prepared contributions to keep Matplotlib maintainable.

Matplotlib maintainers cannot provide one-to-one guidance on this PR. However, if you ask focused, well-researched questions, a community member may be willing to help. 💬

To increase the chance of a productive review:

As the author, you are responsible for driving this PR, which entails doing necessary background research as well as presenting its context and your thought process. If you are a new contributor, or do not know how to fulfill these requirements, we recommend that you familiarize yourself with Matplotlib's development conventions or engage with the community via our Discourse or one of our meetings before submitting code.

If you substantially improve this PR within two weeks, leave a comment and a team member may remove the status: autoclose candidate label and the PR stays open. Cosmetic changes or incomplete fixes will not be sufficient. Maintainers will assess improvements on their own schedule. Please do not ping (@) maintainers.

@evanscastonguay

Copy link
Copy Markdown
Author

Updated the description: I was able to run the SVG comparisons locally (Inkscape) — 107 pass, 4 baselines shift by small/benign amounts (RMS 0.01–1.6, edge drift). Details and the two resolution options are in the PR body. Happy to push whichever direction you prefer.

@timhoffm

timhoffm commented Jun 1, 2026

Copy link
Copy Markdown
Member

You still fail to use the PR template. Contributions not following this will not be considered and closed.

@evanscastonguay

Copy link
Copy Markdown
Author

Closing this. I opened it without properly checking the existing work — #31361 already addresses this at the FillBetweenPolyCollection level, which is cleaner than my SVG-backend change, and the discussion there is rightly leaning toward making vector simplification opt-in rather than on-by-default (which mine isn't). I also should have used the PR template and the AI-disclosure section. Apologies for the duplicate and the noise — I'll follow #31361.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend: svg status: autoclose candidate PRs that are not yet ready for review and may be automatically closed in two weeks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Large file size when using fill_between()

2 participants