You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As discussed a few weeks ago on the dev call, the Cairo backends are less feature-equivalent to the Agg backends.
For example, Pycairo and cairocffi only expose the "toy" font API, so that we cannot correctly apply libraqm full handling of text, as we can only request a font by name and not an explicit file path. See e.g., #28452 or #32084 for the consequences of the toy font API.
Additionally, there are some inconsistencies with the Agg backend wrt blitting and other extended API (you can try changing the default from Agg to Cairo, and see what fails in the test suite.)
Proposed fix
Some options discussed in the call were:
Deprecate the Cairo backends, possibly with a soft-deprecation.
Automatically substitute the Cairo backend by mplcairo if installed
Add some kind of alias to make using mplcairo simpler.
Import mplcairo to the code base instead of the original Cairo backends.
With mplcairo being superior, I think we should not invest any effort in the current cairo implementation
At least we should mark cario as no longer developed and recommend mplcairo instead
I'm sceptical on automatic substitution. This would change behavior and has no easy opt-out mechanism.
We could special-case "mplcairo.*" as a shortcut for "module://mplcairo.*" to make it the blessed cairo implementation.
I have no clear view what importing mplcairo into our codebase would mean.
from a maintainance point of view it would only make sense if there is some sort of commitment that developers beyond @anntzer would care for the code (not necessarily actively develop it, but at least care for severe bugs)
from a dependency point of view, I think nothing changes. Though AFAIK we need to have pycairo/cairodffi installed so that the cairo backend works, and these are not hard dependencies. That's quite ergonomic. Install matplotlib, mplcairo is more clear than matplotlib, pycairo. OTOH that's a more fundamental issue with our current dependency handling, and independent of the cairo topic we may want to more systematically define optional dependencies
On the call there was a discussion of making a special entry point install matplotlib [mplcairo]
I suppose "entry point" is the wrong term and these are the mentioned optional dependencies, sometimes also called dependency groups or dependency extras?
mplcairo has been my daily driver for over 8 years now, it is in a very stable state, although a few issues remain open (matplotlib/mplcairo#19). It is certainly usable (by me...) as a default backend, unlike the builtin cairo backend which is more or less unfixable, as noted by @QuLogic. A few (more-or-less) recent additions to matplotlib haven't made it to mplcairo yet (essentially because no one asked for them), in particular font fallback, and more recently blend groups. However I expect that they will be reasonably easy to add (I already have a vibecoded version of font fallback; and custom blending operators are already available with a bespoke API).
On the other hand, the main reason that drove me to write mplcairo (marker stamping with subpixel precision) is likely(?) going to be fixed soon in Agg (#32108); and the other advantages re: font handling have been implemented in matplotlib 3.11 through the enormous effort of @QuLogic and @jkseppan in particular. I think the main feature that's still only in mplcairo is floating-point buffers (#22227), which is likely also possible to add on Agg's side with a bit of work? That's also a feature that's actually quite useful to have and cannot be faked, in the rare cases where you actually need it. There's also a few more obscure things that cairo provides, e.g. dithering control.
So in practice I guess that, while a builtin mplcairo backend may be more usable (and may see more use) by end users than the current cairo backend, the real advantages aren't that big either. On a more conceptual level, though, I think that having a second "big/complete" backend is nice in that it makes sure that our backend API is actually somewhat generic, and not too tied down to Agg's specifics (indeed, in the early times of mplcairo development, I made a few cleanups to the common backend API on that basis).
Concerning dependencies: Currently, on Windows, mplcairo's wheel just bundles cairo.dll and thus has no external dependency at all. On Linux & macOS there's a dependency on pycairo but the goal is basically just to steal access to the libcairo.{so,dylib} that pycairo ships itself -- if we decide to include the shared library in matplotlib's wheel instead then there's no external dependency involved. (Conversely we can maybe use the same approach on Windows as well, it's just a bit more tedious because all the cairo_* symbols will have to explicitly go through the DLL instead of just being able to do dlopen("libcairo.so", RTLD_GLOBAL) (which is more or less the C way to write from libcairo.so import *).)
"entry point" is the wrong term, what I was suggesting was to special case the matplotlib.use(...) logic to handle the string 'qtmplcairo' and friends to load mplcairo the same way we do for the backends we ship (and fail with an import error if it is missing the same way we do for the GUI toolkits).
Activity
timhoffm commentedon Sep 1, 2026
Some bits of thoughts:
https://github.com/search?q=%2Fmatplotlib%5C.use%5C%28%5B%22%27%5Dcairo%2F+language%3APython+NOT+is%3Afork&type=code&p=1
matplotlib, mplcairois more clear thanmatplotlib, pycairo. OTOH that's a more fundamental issue with our current dependency handling, and independent of the cairo topic we may want to more systematically define optional dependenciesstory645 commentedon Sep 1, 2026
On the call there was a discussion of making a special entry point install
matplotlib [mplcairo]timhoffm commentedon Sep 1, 2026
I suppose "entry point" is the wrong term and these are the mentioned optional dependencies, sometimes also called dependency groups or dependency extras?
anntzer commentedon Sep 3, 2026
mplcairo has been my daily driver for over 8 years now, it is in a very stable state, although a few issues remain open (matplotlib/mplcairo#19). It is certainly usable (by me...) as a default backend, unlike the builtin cairo backend which is more or less unfixable, as noted by @QuLogic. A few (more-or-less) recent additions to matplotlib haven't made it to mplcairo yet (essentially because no one asked for them), in particular font fallback, and more recently blend groups. However I expect that they will be reasonably easy to add (I already have a vibecoded version of font fallback; and custom blending operators are already available with a bespoke API).
On the other hand, the main reason that drove me to write mplcairo (marker stamping with subpixel precision) is likely(?) going to be fixed soon in Agg (#32108); and the other advantages re: font handling have been implemented in matplotlib 3.11 through the enormous effort of @QuLogic and @jkseppan in particular. I think the main feature that's still only in mplcairo is floating-point buffers (#22227), which is likely also possible to add on Agg's side with a bit of work? That's also a feature that's actually quite useful to have and cannot be faked, in the rare cases where you actually need it. There's also a few more obscure things that cairo provides, e.g. dithering control.
So in practice I guess that, while a builtin mplcairo backend may be more usable (and may see more use) by end users than the current cairo backend, the real advantages aren't that big either. On a more conceptual level, though, I think that having a second "big/complete" backend is nice in that it makes sure that our backend API is actually somewhat generic, and not too tied down to Agg's specifics (indeed, in the early times of mplcairo development, I made a few cleanups to the common backend API on that basis).
Concerning dependencies: Currently, on Windows, mplcairo's wheel just bundles cairo.dll and thus has no external dependency at all. On Linux & macOS there's a dependency on pycairo but the goal is basically just to steal access to the libcairo.{so,dylib} that pycairo ships itself -- if we decide to include the shared library in matplotlib's wheel instead then there's no external dependency involved. (Conversely we can maybe use the same approach on Windows as well, it's just a bit more tedious because all the cairo_* symbols will have to explicitly go through the DLL instead of just being able to do
dlopen("libcairo.so", RTLD_GLOBAL)(which is more or less the C way to writefrom libcairo.so import *).)tacaswell commentedon Sep 3, 2026
"entry point" is the wrong term, what I was suggesting was to special case the
matplotlib.use(...)logic to handle the string 'qtmplcairo' and friends to load mplcairo the same way we do for the backends we ship (and fail with an import error if it is missing the same way we do for the GUI toolkits).