mplcairo


Namemplcairo JSON
Version 0.6.1 PyPI version JSON
download
home_pageNone
SummaryA (new) cairo backend for Matplotlib.
upload_time2024-11-11 22:56:39
maintainerNone
docs_urlNone
authorAntony Lee
requires_python>=3.8
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ====================================
A (new) cairo backend for Matplotlib
====================================

| |GitHub| |PyPI| |Fedora Rawhide|

.. |GitHub|
   image:: https://img.shields.io/badge/github-anntzer%2Fmplcairo-brightgreen
   :target: https://github.com/anntzer/mplcairo
.. |PyPI|
   image:: https://img.shields.io/pypi/v/mplcairo.svg?color=brightgreen
   :target: https://pypi.python.org/pypi/mplcairo
.. |Fedora Rawhide|
   image:: https://repology.org/badge/version-for-repo/fedora_rawhide/python:mplcairo.svg?header=Fedora%20Rawhide
   :target: fedora-package_

.. _fedora-package: https://src.fedoraproject.org/rpms/python-mplcairo

.. contents:: :local:

This is a new, essentially complete implementation of a cairo_ backend for
Matplotlib_.  It can be used in combination with a Qt, GTK, Tk, wx, or macOS
UI, or non-interactively (i.e., to save figure to various file formats).

Noteworthy points include:

.. ... sadly, currently not true.

   - Speed (the backend can be up to ~10× faster than Agg, e.g., when stamping
     circular markers of variable colors).

- Improved accuracy (e.g., with marker positioning, quad meshes, and text
  kerning; floating point surfaces are supported with cairo≥1.17.2).
- Optional multithreaded drawing of markers and path collections.
- Optional support for complex text layout (right-to-left languages, etc.) and
  OpenType font features (see `examples/opentype_features.py`_) and variations
  (see `examples/opentype_variations.py`_) (requires cairo≥1.16.0), and partial
  support for color fonts (e.g., emojis), using Raqm_.  **Note** that Raqm
  depends by default on Fribidi, which is licensed under the LGPLv2.1+.
- Support for embedding URLs in PDF (but not SVG) output (requires
  cairo≥1.15.4).
- Support for multi-page output both for PDF and PS (Matplotlib only supports
  multi-page PDF).
- Support for custom blend modes (see `examples/operators.py`_).
- Improved font embedding in vector formats: fonts are typically subsetted and
  embedded in their native format (Matplotlib≥3.5 also provides improved font
  embedding).

.. _cairo: https://www.cairographics.org/
.. _Matplotlib: http://matplotlib.org/
.. _Raqm: https://github.com/HOST-Oman/libraqm
.. _examples/opentype_features.py: examples/opentype_features.py
.. _examples/opentype_variations.py: examples/opentype_variations.py
.. _examples/operators.py: examples/operators.py

Installation
============

mplcairo requires

- Python≥3.7,
- Matplotlib≥2.2 (declared as ``install_requires``),
- on Linux and macOS, pycairo≥1.16.0 [#]_ (declared as ``install_requires``),
- on Windows, cairo≥1.13.1 [#]_ (shipped with the wheel).

It is recommended to use cairo≥1.17.4.

Additionally, building mplcairo from source requires

- pybind11≥2.6.0 [#]_ (declared as ``setup_requires``),
- pycairo≥1.16.0 (declared as ``setup_requires``).

As usual, install using pip:

.. code-block:: sh

   $ pip install mplcairo  # from PyPI
   $ pip install git+https://github.com/matplotlib/mplcairo  # from Github

Note that wheels are not available for macOS<10.13, because the libc++ included
with these versions is too old and vendoring of libc++ appears to be fragile.

mplcairo can use Raqm_ (≥0.7.0; ≥0.7.2 is recommended as it provides better
emoji support, especially in the presence of ligatures) for complex text layout
and handling of OpenType font features.  Refer to the instructions on that
project's website for installation on Linux and macOS.  On Windows, consider
using Christoph Gohlke's `build <gohlke-libraqm_>`_ (the directory containing
``libraqm.dll`` and ``libfribidi-0.dll`` need to be added to the `DLL search
path <add_dll_directory_>`_).

.. _gohlke-libraqm: https://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow
.. _add_dll_directory: https://docs.python.org/3/library/os.html#os.add_dll_directory

.. [#] pycairo 1.16.0 added ``get_include()``.

   We do not actually rely on pycairo's Python bindings.  Rather, the
   dependency on pycairo (≥1.16.0) conveniently specifies a dependency on
   cairo (≥1.13.1) itself, and allows us to load cairo at runtime instead of
   linking to it (simplifying the build of self-contained wheels).

   On Windows, this strategy is (AFAIK) not possible, so we explicitly link
   against the cairo DLL.

.. [#] cairo 1.13.1 matches the oldest version supported by pycairo 1.16.0.

   cairo 1.15.4 added support for PDF metadata and links; the presence of this
   feature is detected at runtime.

   cairo 1.16.0 added support for font variations; the presence of this feature
   is detected at runtime.

   cairo 1.17.2 added support for floating point surfaces, usable with
   ``mplcairo.set_options(float_surface=True)``; the presence of this feature
   is detected at runtime.  However, cairo 1.17.2 (and only that version) also
   has a bug that causes (in particular) polar gridlines to be incorrectly
   cropped.  This bug was fixed in 2d1a137.

   cairo 1.17.4 fixed a rare crash in rasterization (in dfe3aa6).

   cairo 1.17.8 fixed a crash when outputting in the cairo-script format (in
   6a81bf8).

.. [#] pybind11 2.6.0 is needed to support Python 3.9.

On Fedora, the package is available as `python-mplcairo <fedora-package_>`_.

Building/packaging
==================

This section is only relevant if you wish to build mplcairo yourself, or
package it for redistribution.  Otherwise, proceed to the Use_ section.

In all cases, once the dependencies described below are installed, mplcairo
can be built and installed using any of the standard commands (``pip wheel
--no-deps .``, ``pip install .``, ``pip install -e .`` and ``python setup.py
build_ext -i`` being the most relevant ones).

Unix
----

The following additional dependencies are required:

- a C++ compiler with C++17 support, e.g. GCC≥7.2 or Clang≥5.0.

- cairo and FreeType headers, and pkg-config information to locate them.

  If using conda, they can be installed using ::

     conda install -y -c conda-forge pycairo pkg-config

  as pycairo (also a dependency) depends on cairo, which depends on freetype.
  Note that cairo and pkg-config from the ``anaconda`` channel will *not* work.

  On Linux, they can also be installed with your distribution's package manager
  (Arch: ``cairo``, Debian/Ubuntu: ``libcairo2-dev``, Fedora: ``cairo-devel``).

Raqm (≥0.2) headers are also needed, but will be automatically downloaded if
not found.

Linux
`````

conda's compilers (``gxx_linux-64`` on the ``anaconda`` channel) `currently
interact poorly with installing cairo and pkg-config from conda-forge
<conda-build-2523_>`_, so you are on your own to install a recent compiler
(e.g., using your distribution's package manager).  You may want to set the
``CC`` and ``CXX`` environment variables to point to your C++ compiler if it is
nonstandard [#]_.  In that case, be careful to set them to e.g. ``g++-7`` and
**not** ``gcc-7``, otherwise the compilation will succeed but the shared object
will be mis-linked and fail to load.

The manylinux wheel is built using `tools/build-manylinux-wheel.sh`_.

.. _conda-build-2523: https://github.com/conda/conda-build/issues/2523
.. [#] ``distutils`` uses ``CC`` for *compiling* C++ sources but ``CXX`` for
   linking them (don't ask).  You may run into additional issues if ``CC`` or
   ``CXX`` has multiple words; e.g., if ``CC`` is set to ``ccache g++``, you
   also need to set ``CXX`` to ``ccache gcc``.
.. _tools/build-manylinux-wheel.sh: tools/build-manylinux-wheel.sh

macOS
`````

Clang≥5.0 can be installed from ``conda``'s ``anaconda`` channel (``conda
install -c anaconda clangxx_osx-64``), or can also be installed with Homebrew
(``brew install llvm``).  Note that Homebrew's llvm formula is keg-only, i.e.
it requires manual modifications to the PATH and LDFLAGS (as documented by
``brew info llvm``).

On macOS<10.14, it is additionally necessary to use clang<8.0 (e.g. with ``brew
install llvm@7``) as clang 8.0 appears to believe that code relying on C++17
can only be run on macOS≥10.14+.

The macOS wheel is built using ``tools/build-macos-wheel.sh``, which relies on
delocate-wheel_ (to vendor a recent version of libc++).  Currently, it can only
be built from a Homebrew-clang wheel, not a conda-clang wheel (due to some path
intricacies...).

.. _delocate-wheel: https://github.com/matthew-brett/delocate

Windows
-------

The following additional dependencies are required:

- VS2019 (The exact minimum version is unknown, but it is known that mplcairo
  fails to build on the Github Actions ``windows-2016`` agent and requires the
  ``windows-2019`` agent.)

- cairo headers and import and dynamic libraries (``cairo.lib`` and
  ``cairo.dll``) *with FreeType support*.  Note that this excludes, in
  particular, most Anaconda and conda-forge builds: they do not include
  FreeType support.

  The currently preferred solution is to get the headers e.g. from a Linux
  distribution package, the DLL from a pycairo wheel (e.g. from PyPI), and
  generate the import library oneself using ``dumpbin`` and ``lib``.

  Alternatively, very recent conda-forge builds (≥1.16.0 build 1005) do
  include FreeType support.  In order to use them, the include path needs to be
  modified as described below.  (This is currently intentionally disabled by
  default to avoid confusing errors if the cairo build is too old.)

- FreeType headers and import and dynamic libraries (``freetype.lib`` and
  ``freetype.dll``), which can be retrieved from
  https://github.com/ubawurinna/freetype-windows-binaries, or alternatively
  using conda::

     conda install -y freetype

The (standard) |CL|_ and |LINK|_ environment variables (which always get
prepended respectively to the invocations of the compiler and the linker)
should be set as follows::

   set CL=/IC:\path\to\dir\containing\cairo.h /IC:\same\for\ft2build.h
   set LINK=/LIBPATH:C:\path\to\dir\containing\cairo.lib /LIBPATH:C:\same\for\freetype.lib

In particular, in order to use a conda-forge cairo (as described above),
``{sys.prefix}\Library\include\cairo`` needs to be added to the include path.

Moreover, we also need to find ``cairo.dll`` and ``freetype.dll`` and copy
them next to ``mplcairo``'s extension module.  As the dynamic libraries are
typically found next to import libraries, we search the ``/LIBPATH:`` entries
in the ``LINK`` environment variable and copy the first ``cairo.dll`` and
``freetype.dll`` found there.

The script ``tools/build-windows-wheel.py`` automates the retrieval of the
cairo (assuming that pycairo is already installed) and FreeType DLLs, and the
wheel build.

.. |CL| replace:: ``CL``
.. _CL: https://docs.microsoft.com/en-us/cpp/build/reference/cl-environment-variables
.. |LINK| replace:: ``LINK``
.. _LINK: https://docs.microsoft.com/en-us/cpp/build/reference/link-environment-variables

Use
===

On Linux and Windows, mplcairo can be used as any normal Matplotlib backend:
call e.g. ``matplotlib.use("module://mplcairo.qt")`` before importing pyplot,
add a ``backend: module://mplcairo.qt`` line in your ``matplotlibrc``, or set
the ``MPLBACKEND`` environment variable to ``module://mplcairo.qt``.  More
specifically, the following backends are provided:

- ``module://mplcairo.base`` (No GUI, but can output to EPS, PDF, PS, SVG, and
  SVGZ using cairo's implementation, rather than Matplotlib's),
- ``module://mplcairo.gtk`` (GTK widget, copying data from a cairo image
  surface — GTK3 or GTK4 can be selected by calling
  ``gi.require_version("Gtk", "3.0")`` or ``gi.require_version("Gtk", "4.0")``
  before importing the backend),
- ``module://mplcairo.gtk_native`` (GTK widget, directly drawn onto as a
  native surface; does not and cannot support blitting — see above for version
  selection),
- ``module://mplcairo.qt`` (Qt widget, copying data from a cairo image
  surface — select the binding to use by importing it before mplcairo, or by
  setting the ``QT_API`` environment variable),
- ``module://mplcairo.tk`` (Tk widget, copying data from a cairo image
  surface),
- ``module://mplcairo.wx`` (wx widget, copying data from a cairo image
  surface),
- ``module://mplcairo.macosx`` (macOS widget, copying data from a cairo image
  surface).

On macOS, prior to Matplotlib 3.8, **it was necessary to explicitly import
mplcairo before importing Matplotlib** (unless your Matplotlib is built with
``system_freetype = True``).  A practical option was to import mplcairo, then
call e.g. ``matplotlib.use("module://mplcairo.macosx")``.

Jupyter is entirely unsupported (patches would be appreciated).  One
possibility is to set the ``MPLCAIRO_PATCH_AGG`` environment variable to a
non-empty value *before importing Matplotlib*; this fully replaces the Agg
renderer by the cairo renderer throughout Matplotlib.  However, this approach
is inefficient (due to the need of copies and conversions between premultiplied
ARGB32 and straight RGBA8888 buffers); additionally, it does not work with
the wx and macosx backends due to peculiarities of the corresponding canvas
classes.  On the other hand, this is currently the only way in which the
webagg-based backends (e.g., Jupyter's interactive widgets) can use mplcairo.

At import-time, mplcairo will attempt to load Raqm_.  The use of that library
can be controlled and checked using the ``set_options`` and ``get_options``
functions.

The examples_ directory contains a few cases where the output of this renderer
is arguably more accurate than the one of the default renderer, Agg:

- circle_markers.py_ and square_markers.py_: more accurate and faster marker
  stamping.
- marker_stamping.py_: more accurate marker stamping.
- quadmesh.py_: better antialiasing of quad meshes, fewer artefacts with
  masked data.
- text_kerning.py_: improved text kerning.

.. _examples: examples/
.. _circle_markers.py: examples/circle_markers.py
.. _square_markers.py: examples/square_markers.py
.. _marker_stamping.py: examples/marker_stamping.py
.. _quadmesh.py: examples/quadmesh.py
.. _text_kerning.py: examples/text_kerning.py

Benchmarks
==========

Install (in the virtualenv) ``pytest>=3.1.0`` and ``pytest-benchmark``, then
call (e.g.):

.. code-block:: sh

   pytest --benchmark-group-by=fullfunc --benchmark-timer=time.process_time

Keep in mind that conda-forge's cairo is (on my setup) ~2× slower than a
"native" build of cairo.

Test suite
==========

Run ``run-mpl-test-suite.py`` (which depends on ``pytest>=3.2.2``) to run the
Matplotlib test suite with the Agg backend patched by the mplcairo backend.
Note that Matplotlib must be installed with its test data, which is not the
case when it is installed from conda or from most Linux distributions; instead,
it should be installed from PyPI or from source.

Nearly all image comparison tests "fail" as the renderers are fundamentally
different; currently, the intent is to manually check the diff images.  Passing
``--tolerance=inf`` marks these tests as "passed" (while still textually
reporting the image differences) so that one can spot issues not related to
rendering differences.  In practice, ``--tolerance=50`` appears to be enough.

Some other (non-image-comparison) tests are also known to fail (they are listed
in ``ISSUES.rst``, with the relevant explanations), and automatically skipped.

Run ``run-examples.py`` to run some examples that exercise some more aspects of
mplcairo.

Notes
=====

Antialiasing
------------

The artist antialiasing property can be set to any of the ``cairo_antialias_t``
enum values, or ``True`` (the default) or ``False`` (which is synonym to
``NONE``).

Setting antialiasing to ``True`` uses ``FAST`` antialiasing for lines thicker
than 1/3px and ``BEST`` for lines thinner than that: for lines thinner
than 1/3px, the former leads to artefacts such as lines disappearing in
certain sections (see e.g. ``test_cycles.test_property_collision_plot`` after
forcing the antialiasing to ``FAST``).  The threshold of 1/3px was determined
empirically, see `examples/thin_line_antialiasing.py`_.

.. _examples/thin_line_antialiasing.py: examples/thin_line_antialiasing.py

Note that in order to set the ``lines.antialiased`` or ``patch.antialiased``
rcparams to a ``cairo_antialias_t`` enum value, it is necessary to bypass
rcparam validation, using, e.g.

.. code-block:: python

   dict.__setitem__(plt.rcParams, "lines.antialiased", antialias_t.FAST)

The ``text.antialiased`` rcparam can likewise be set to any
``cairo_antialias_t`` enum value, or ``True`` (the default, which maps to
``SUBPIXEL`` — ``GRAY`` is not sufficient to benefit from Raqm_'s subpixel
positioning; see also `cairo issue #152 <cairo-152_>`_) or ``False`` (which
maps to ``NONE``).

.. _cairo-152: https://gitlab.freedesktop.org/cairo/cairo/issues/152

Note that in rare cases, on cairo<1.17.4, ``FAST`` antialiasing can trigger a
"double free or corruption" bug in cairo (`#44 <cairo-44_>`_).  If you hit this
problem, consider using ``BEST`` or ``NONE`` antialiasing (depending on your
quality and speed requirements).

.. _cairo-44: https://gitlab.freedesktop.org/cairo/cairo/issues/44

Fast drawing
------------

For fast drawing of path with many segments, the ``agg.path.chunksize`` rcparam
should be set to e.g. 1000 (see `examples/time_drawing_per_element.py`_ for the
determination of this value); this causes longer paths to be split into
individually rendered sections of 1000 segments each (directly rendering longer
paths appears to have slightly superlinear complexity).

.. _examples/time_drawing_per_element.py: examples/time_drawing_per_element.py

Simplification threshold
------------------------

The ``path.simplify_threshold`` rcparam is used to control the accuracy of
marker stamping, down to an arbitrarily chosen threshold of 1/16px.  If the
threshold is set to a lower value, the exact (slower) marker drawing path will
be used.  Marker stamping is also implemented for scatter plots (which can have
multiple colors).  Likewise, markers of different sizes get mapped into markers
of discretized sizes, with an error bounded by the threshold.

**NOTE**: ``pcolor`` and mplot3d's ``plot_surface`` display some artefacts
where the facets join each other.  This is because these functions internally
use a ``PathCollection``; this triggers the approximate stamping, and
even without it (by setting ``path.simplify_threshold`` to zero), cairo's
rasterization of the edge between the facets is poor.  ``pcolormesh`` (which
internally uses a ``QuadMesh``) should generally be preferred over ``pcolor``
anyways.  ``plot_surface`` could likewise instead represent the surface using
``QuadMesh``, which is drawn without such artefacts.

Font formats and features
-------------------------

In order to use a specific font that Matplotlib may be unable to use, pass a
filename directly:

.. code-block:: python

   from matplotlib.font_manager import FontProperties
   fig.text(.5, .5, "hello, world",
            fontproperties=FontProperties(fname="/path/to/font.ttf"))

or more simply, with Matplotlib≥3.3:

.. code-block:: python

   from pathlib import Path
   fig.text(.5, .5, "hello, world", font=Path("/path/to/font.ttf"))

mplcairo still relies on Matplotlib's font cache, so fonts unsupported by
Matplotlib remain unavailable by other means.

For TTC fonts (and, more generally, font formats that include multiple font
faces in a single file), the *n*\th font (*n*\≥0) can be selected by appending
``#n`` to the filename (e.g., ``"/path/to/font.ttc#1"``).

OpenType font features can be selected by appending ``|feature,...``
to the filename, followed by a `HarfBuzz feature string`_ (e.g.,
``"/path/to/font.otf|frac,onum"``); see `examples/opentype_features.py`_.  A
language_ tag can likewise be set with ``|language=...``; currently, this
always applies to the whole buffer, but a PR adding support for slicing syntax
(similar to font features) would be considered.

OpenType font variations can be selected by appending an additional ``|`` to
the filename, followed by a `Cairo font variation string`_ (e.g.,
``"/path/to/font.otf||wdth=75"``); see `examples/opentype_variations.py`_. This
support requires Cairo>=1.16. Note that features are parsed first, so if you do
not wish to specify any features, you must specify an empty set with two pipes,
i.e., ``font.otf|variations`` will treat ``variations`` as features, *not*
variations.

.. _HarfBuzz feature string: https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-feature-from-string
.. _Cairo font variation string: https://www.cairographics.org/manual/cairo-cairo-font-options-t.html#cairo-font-options-set-variations
.. _language: https://host-oman.github.io/libraqm/raqm-Raqm.html#raqm-set-language

The syntaxes for selecting TTC subfonts and OpenType font features and language
tags are **experimental** and may change, especially if such features are
implemented in Matplotlib itself.

Color fonts (e.g. emojis) are handled.

Multi-page output
-----------------

Matplotlib's ``PdfPages`` class is deeply tied with the builtin ``backend_pdf``
(in fact, it cannot even be used with Matplotlib's own cairo backend).
Instead, use ``mplcairo.multipage.MultiPage`` for multi-page PDF and PS output.
The API is similar:

.. code-block:: python

   from mplcairo.multipage import MultiPage

   fig1 = ...
   fig2 = ...
   with MultiPage(path_or_stream, metadata=...) as mp:
       mp.savefig(fig1)
       mp.savefig(fig2)

See the class' docstring for additional information.

Version control for vector formats
----------------------------------

cairo is able to write PDF 1.4 and 1.5 (defaulting to 1.5), PostScript levels 2
and 3 (defaulting to 3), and SVG versions 1.1 and 1.2 (defaulting to 1.1).
This can be controlled by passing a *metadata* dict to ``savefig`` with a
``MaxVersion`` entry, which must be one of the strings ``"1.4"``/``"1.5"`` (for
pdf), ``"2"``/``"3"`` (for ps), or ``"1.1"``/``"1.2"`` (for svg).

``cairo-script`` output
-----------------------

Setting the ``MPLCAIRO_SCRIPT_SURFACE`` environment variable *before mplcairo
is imported* to ``vector`` or ``raster`` allows one to save figures (with
``savefig``) in the ``.cairoscript`` format, which is a "native script that
matches the cairo drawing model".  The value of the variable determines the
rendering path used (e.g., whether marker stamping is used at all).  This may
be helpful for troubleshooting purposes.

Note that cairo-script output is generally broken on cairo≤1.17.8.

Markers at Bézier control points
--------------------------------

``draw_markers`` draws a marker at each control point of the given path, which
is the documented behavior, even though all builtin renderers only draw markers
at straight or Bézier segment ends.

Known differences
=================

Due to missing support from cairo:

- SVG output does not support global metadata or set URLs or ids on any
  element, as cairo provides no support to do so.
- PS output does not respect SOURCE_DATE_EPOCH.
- PS output does not support the ``Creator`` metadata key; however it supports
  the ``Title`` key.
- The following rcparams have no effect:

  - ``pdf.fonttype`` (font type is selected by cairo internally),
  - ``pdf.inheritcolor`` (effectively always ``False``),
  - ``pdf.use14corefonts`` (effectively always ``False``),
  - ``ps.fonttype`` (font type is selected by cairo internally),
  - ``ps.useafm`` (effectively always ``False``),
  - ``svg.fonttype`` (effectively always ``"path"``, see `cairo issue #253
    <cairo-253_>`_),
  - ``svg.hashsalt``.

Additionally, the ``quality``, ``optimize``, and ``progressive`` parameters to
``savefig``, which have been removed in Matplotlib 3.5, are not supported.

.. _cairo-253: https://gitlab.freedesktop.org/cairo/cairo/issues/253

Possible optimizations
======================

- Cache eviction policy and persistent cache for ``draw_path_collection``.
- Use QtOpenGLWidget and the cairo-gl backend.

What about the already existing cairo (gtk/qt/wx/tk/...cairo) backends?
=============================================================================

They are very slow (try running `examples/mplot3d/wire3d_animation.py`_) and
render math poorly (try ``title(r"$\sqrt{2}$")``).

.. _examples/mplot3d/wire3d_animation.py: examples/mplot3d/wire3d_animation.py

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "mplcairo",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "Antony Lee",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/1f/d6/2d24fc6152db8161075b18070eda687b9c5c2428980b309184fb0653fab6/mplcairo-0.6.1.tar.gz",
    "platform": null,
    "description": "====================================\nA (new) cairo backend for Matplotlib\n====================================\n\n| |GitHub| |PyPI| |Fedora Rawhide|\n\n.. |GitHub|\n   image:: https://img.shields.io/badge/github-anntzer%2Fmplcairo-brightgreen\n   :target: https://github.com/anntzer/mplcairo\n.. |PyPI|\n   image:: https://img.shields.io/pypi/v/mplcairo.svg?color=brightgreen\n   :target: https://pypi.python.org/pypi/mplcairo\n.. |Fedora Rawhide|\n   image:: https://repology.org/badge/version-for-repo/fedora_rawhide/python:mplcairo.svg?header=Fedora%20Rawhide\n   :target: fedora-package_\n\n.. _fedora-package: https://src.fedoraproject.org/rpms/python-mplcairo\n\n.. contents:: :local:\n\nThis is a new, essentially complete implementation of a cairo_ backend for\nMatplotlib_.  It can be used in combination with a Qt, GTK, Tk, wx, or macOS\nUI, or non-interactively (i.e., to save figure to various file formats).\n\nNoteworthy points include:\n\n.. ... sadly, currently not true.\n\n   - Speed (the backend can be up to ~10\u00d7 faster than Agg, e.g., when stamping\n     circular markers of variable colors).\n\n- Improved accuracy (e.g., with marker positioning, quad meshes, and text\n  kerning; floating point surfaces are supported with cairo\u22651.17.2).\n- Optional multithreaded drawing of markers and path collections.\n- Optional support for complex text layout (right-to-left languages, etc.) and\n  OpenType font features (see `examples/opentype_features.py`_) and variations\n  (see `examples/opentype_variations.py`_) (requires cairo\u22651.16.0), and partial\n  support for color fonts (e.g., emojis), using Raqm_.  **Note** that Raqm\n  depends by default on Fribidi, which is licensed under the LGPLv2.1+.\n- Support for embedding URLs in PDF (but not SVG) output (requires\n  cairo\u22651.15.4).\n- Support for multi-page output both for PDF and PS (Matplotlib only supports\n  multi-page PDF).\n- Support for custom blend modes (see `examples/operators.py`_).\n- Improved font embedding in vector formats: fonts are typically subsetted and\n  embedded in their native format (Matplotlib\u22653.5 also provides improved font\n  embedding).\n\n.. _cairo: https://www.cairographics.org/\n.. _Matplotlib: http://matplotlib.org/\n.. _Raqm: https://github.com/HOST-Oman/libraqm\n.. _examples/opentype_features.py: examples/opentype_features.py\n.. _examples/opentype_variations.py: examples/opentype_variations.py\n.. _examples/operators.py: examples/operators.py\n\nInstallation\n============\n\nmplcairo requires\n\n- Python\u22653.7,\n- Matplotlib\u22652.2 (declared as ``install_requires``),\n- on Linux and macOS, pycairo\u22651.16.0 [#]_ (declared as ``install_requires``),\n- on Windows, cairo\u22651.13.1 [#]_ (shipped with the wheel).\n\nIt is recommended to use cairo\u22651.17.4.\n\nAdditionally, building mplcairo from source requires\n\n- pybind11\u22652.6.0 [#]_ (declared as ``setup_requires``),\n- pycairo\u22651.16.0 (declared as ``setup_requires``).\n\nAs usual, install using pip:\n\n.. code-block:: sh\n\n   $ pip install mplcairo  # from PyPI\n   $ pip install git+https://github.com/matplotlib/mplcairo  # from Github\n\nNote that wheels are not available for macOS<10.13, because the libc++ included\nwith these versions is too old and vendoring of libc++ appears to be fragile.\n\nmplcairo can use Raqm_ (\u22650.7.0; \u22650.7.2 is recommended as it provides better\nemoji support, especially in the presence of ligatures) for complex text layout\nand handling of OpenType font features.  Refer to the instructions on that\nproject's website for installation on Linux and macOS.  On Windows, consider\nusing Christoph Gohlke's `build <gohlke-libraqm_>`_ (the directory containing\n``libraqm.dll`` and ``libfribidi-0.dll`` need to be added to the `DLL search\npath <add_dll_directory_>`_).\n\n.. _gohlke-libraqm: https://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow\n.. _add_dll_directory: https://docs.python.org/3/library/os.html#os.add_dll_directory\n\n.. [#] pycairo 1.16.0 added ``get_include()``.\n\n   We do not actually rely on pycairo's Python bindings.  Rather, the\n   dependency on pycairo (\u22651.16.0) conveniently specifies a dependency on\n   cairo (\u22651.13.1) itself, and allows us to load cairo at runtime instead of\n   linking to it (simplifying the build of self-contained wheels).\n\n   On Windows, this strategy is (AFAIK) not possible, so we explicitly link\n   against the cairo DLL.\n\n.. [#] cairo 1.13.1 matches the oldest version supported by pycairo 1.16.0.\n\n   cairo 1.15.4 added support for PDF metadata and links; the presence of this\n   feature is detected at runtime.\n\n   cairo 1.16.0 added support for font variations; the presence of this feature\n   is detected at runtime.\n\n   cairo 1.17.2 added support for floating point surfaces, usable with\n   ``mplcairo.set_options(float_surface=True)``; the presence of this feature\n   is detected at runtime.  However, cairo 1.17.2 (and only that version) also\n   has a bug that causes (in particular) polar gridlines to be incorrectly\n   cropped.  This bug was fixed in 2d1a137.\n\n   cairo 1.17.4 fixed a rare crash in rasterization (in dfe3aa6).\n\n   cairo 1.17.8 fixed a crash when outputting in the cairo-script format (in\n   6a81bf8).\n\n.. [#] pybind11 2.6.0 is needed to support Python 3.9.\n\nOn Fedora, the package is available as `python-mplcairo <fedora-package_>`_.\n\nBuilding/packaging\n==================\n\nThis section is only relevant if you wish to build mplcairo yourself, or\npackage it for redistribution.  Otherwise, proceed to the Use_ section.\n\nIn all cases, once the dependencies described below are installed, mplcairo\ncan be built and installed using any of the standard commands (``pip wheel\n--no-deps .``, ``pip install .``, ``pip install -e .`` and ``python setup.py\nbuild_ext -i`` being the most relevant ones).\n\nUnix\n----\n\nThe following additional dependencies are required:\n\n- a C++ compiler with C++17 support, e.g. GCC\u22657.2 or Clang\u22655.0.\n\n- cairo and FreeType headers, and pkg-config information to locate them.\n\n  If using conda, they can be installed using ::\n\n     conda install -y -c conda-forge pycairo pkg-config\n\n  as pycairo (also a dependency) depends on cairo, which depends on freetype.\n  Note that cairo and pkg-config from the ``anaconda`` channel will *not* work.\n\n  On Linux, they can also be installed with your distribution's package manager\n  (Arch: ``cairo``, Debian/Ubuntu: ``libcairo2-dev``, Fedora: ``cairo-devel``).\n\nRaqm (\u22650.2) headers are also needed, but will be automatically downloaded if\nnot found.\n\nLinux\n`````\n\nconda's compilers (``gxx_linux-64`` on the ``anaconda`` channel) `currently\ninteract poorly with installing cairo and pkg-config from conda-forge\n<conda-build-2523_>`_, so you are on your own to install a recent compiler\n(e.g., using your distribution's package manager).  You may want to set the\n``CC`` and ``CXX`` environment variables to point to your C++ compiler if it is\nnonstandard [#]_.  In that case, be careful to set them to e.g. ``g++-7`` and\n**not** ``gcc-7``, otherwise the compilation will succeed but the shared object\nwill be mis-linked and fail to load.\n\nThe manylinux wheel is built using `tools/build-manylinux-wheel.sh`_.\n\n.. _conda-build-2523: https://github.com/conda/conda-build/issues/2523\n.. [#] ``distutils`` uses ``CC`` for *compiling* C++ sources but ``CXX`` for\n   linking them (don't ask).  You may run into additional issues if ``CC`` or\n   ``CXX`` has multiple words; e.g., if ``CC`` is set to ``ccache g++``, you\n   also need to set ``CXX`` to ``ccache gcc``.\n.. _tools/build-manylinux-wheel.sh: tools/build-manylinux-wheel.sh\n\nmacOS\n`````\n\nClang\u22655.0 can be installed from ``conda``'s ``anaconda`` channel (``conda\ninstall -c anaconda clangxx_osx-64``), or can also be installed with Homebrew\n(``brew install llvm``).  Note that Homebrew's llvm formula is keg-only, i.e.\nit requires manual modifications to the PATH and LDFLAGS (as documented by\n``brew info llvm``).\n\nOn macOS<10.14, it is additionally necessary to use clang<8.0 (e.g. with ``brew\ninstall llvm@7``) as clang 8.0 appears to believe that code relying on C++17\ncan only be run on macOS\u226510.14+.\n\nThe macOS wheel is built using ``tools/build-macos-wheel.sh``, which relies on\ndelocate-wheel_ (to vendor a recent version of libc++).  Currently, it can only\nbe built from a Homebrew-clang wheel, not a conda-clang wheel (due to some path\nintricacies...).\n\n.. _delocate-wheel: https://github.com/matthew-brett/delocate\n\nWindows\n-------\n\nThe following additional dependencies are required:\n\n- VS2019 (The exact minimum version is unknown, but it is known that mplcairo\n  fails to build on the Github Actions ``windows-2016`` agent and requires the\n  ``windows-2019`` agent.)\n\n- cairo headers and import and dynamic libraries (``cairo.lib`` and\n  ``cairo.dll``) *with FreeType support*.  Note that this excludes, in\n  particular, most Anaconda and conda-forge builds: they do not include\n  FreeType support.\n\n  The currently preferred solution is to get the headers e.g. from a Linux\n  distribution package, the DLL from a pycairo wheel (e.g. from PyPI), and\n  generate the import library oneself using ``dumpbin`` and ``lib``.\n\n  Alternatively, very recent conda-forge builds (\u22651.16.0 build 1005) do\n  include FreeType support.  In order to use them, the include path needs to be\n  modified as described below.  (This is currently intentionally disabled by\n  default to avoid confusing errors if the cairo build is too old.)\n\n- FreeType headers and import and dynamic libraries (``freetype.lib`` and\n  ``freetype.dll``), which can be retrieved from\n  https://github.com/ubawurinna/freetype-windows-binaries, or alternatively\n  using conda::\n\n     conda install -y freetype\n\nThe (standard) |CL|_ and |LINK|_ environment variables (which always get\nprepended respectively to the invocations of the compiler and the linker)\nshould be set as follows::\n\n   set CL=/IC:\\path\\to\\dir\\containing\\cairo.h /IC:\\same\\for\\ft2build.h\n   set LINK=/LIBPATH:C:\\path\\to\\dir\\containing\\cairo.lib /LIBPATH:C:\\same\\for\\freetype.lib\n\nIn particular, in order to use a conda-forge cairo (as described above),\n``{sys.prefix}\\Library\\include\\cairo`` needs to be added to the include path.\n\nMoreover, we also need to find ``cairo.dll`` and ``freetype.dll`` and copy\nthem next to ``mplcairo``'s extension module.  As the dynamic libraries are\ntypically found next to import libraries, we search the ``/LIBPATH:`` entries\nin the ``LINK`` environment variable and copy the first ``cairo.dll`` and\n``freetype.dll`` found there.\n\nThe script ``tools/build-windows-wheel.py`` automates the retrieval of the\ncairo (assuming that pycairo is already installed) and FreeType DLLs, and the\nwheel build.\n\n.. |CL| replace:: ``CL``\n.. _CL: https://docs.microsoft.com/en-us/cpp/build/reference/cl-environment-variables\n.. |LINK| replace:: ``LINK``\n.. _LINK: https://docs.microsoft.com/en-us/cpp/build/reference/link-environment-variables\n\nUse\n===\n\nOn Linux and Windows, mplcairo can be used as any normal Matplotlib backend:\ncall e.g. ``matplotlib.use(\"module://mplcairo.qt\")`` before importing pyplot,\nadd a ``backend: module://mplcairo.qt`` line in your ``matplotlibrc``, or set\nthe ``MPLBACKEND`` environment variable to ``module://mplcairo.qt``.  More\nspecifically, the following backends are provided:\n\n- ``module://mplcairo.base`` (No GUI, but can output to EPS, PDF, PS, SVG, and\n  SVGZ using cairo's implementation, rather than Matplotlib's),\n- ``module://mplcairo.gtk`` (GTK widget, copying data from a cairo image\n  surface \u2014 GTK3 or GTK4 can be selected by calling\n  ``gi.require_version(\"Gtk\", \"3.0\")`` or ``gi.require_version(\"Gtk\", \"4.0\")``\n  before importing the backend),\n- ``module://mplcairo.gtk_native`` (GTK widget, directly drawn onto as a\n  native surface; does not and cannot support blitting \u2014 see above for version\n  selection),\n- ``module://mplcairo.qt`` (Qt widget, copying data from a cairo image\n  surface \u2014 select the binding to use by importing it before mplcairo, or by\n  setting the ``QT_API`` environment variable),\n- ``module://mplcairo.tk`` (Tk widget, copying data from a cairo image\n  surface),\n- ``module://mplcairo.wx`` (wx widget, copying data from a cairo image\n  surface),\n- ``module://mplcairo.macosx`` (macOS widget, copying data from a cairo image\n  surface).\n\nOn macOS, prior to Matplotlib 3.8, **it was necessary to explicitly import\nmplcairo before importing Matplotlib** (unless your Matplotlib is built with\n``system_freetype = True``).  A practical option was to import mplcairo, then\ncall e.g. ``matplotlib.use(\"module://mplcairo.macosx\")``.\n\nJupyter is entirely unsupported (patches would be appreciated).  One\npossibility is to set the ``MPLCAIRO_PATCH_AGG`` environment variable to a\nnon-empty value *before importing Matplotlib*; this fully replaces the Agg\nrenderer by the cairo renderer throughout Matplotlib.  However, this approach\nis inefficient (due to the need of copies and conversions between premultiplied\nARGB32 and straight RGBA8888 buffers); additionally, it does not work with\nthe wx and macosx backends due to peculiarities of the corresponding canvas\nclasses.  On the other hand, this is currently the only way in which the\nwebagg-based backends (e.g., Jupyter's interactive widgets) can use mplcairo.\n\nAt import-time, mplcairo will attempt to load Raqm_.  The use of that library\ncan be controlled and checked using the ``set_options`` and ``get_options``\nfunctions.\n\nThe examples_ directory contains a few cases where the output of this renderer\nis arguably more accurate than the one of the default renderer, Agg:\n\n- circle_markers.py_ and square_markers.py_: more accurate and faster marker\n  stamping.\n- marker_stamping.py_: more accurate marker stamping.\n- quadmesh.py_: better antialiasing of quad meshes, fewer artefacts with\n  masked data.\n- text_kerning.py_: improved text kerning.\n\n.. _examples: examples/\n.. _circle_markers.py: examples/circle_markers.py\n.. _square_markers.py: examples/square_markers.py\n.. _marker_stamping.py: examples/marker_stamping.py\n.. _quadmesh.py: examples/quadmesh.py\n.. _text_kerning.py: examples/text_kerning.py\n\nBenchmarks\n==========\n\nInstall (in the virtualenv) ``pytest>=3.1.0`` and ``pytest-benchmark``, then\ncall (e.g.):\n\n.. code-block:: sh\n\n   pytest --benchmark-group-by=fullfunc --benchmark-timer=time.process_time\n\nKeep in mind that conda-forge's cairo is (on my setup) ~2\u00d7 slower than a\n\"native\" build of cairo.\n\nTest suite\n==========\n\nRun ``run-mpl-test-suite.py`` (which depends on ``pytest>=3.2.2``) to run the\nMatplotlib test suite with the Agg backend patched by the mplcairo backend.\nNote that Matplotlib must be installed with its test data, which is not the\ncase when it is installed from conda or from most Linux distributions; instead,\nit should be installed from PyPI or from source.\n\nNearly all image comparison tests \"fail\" as the renderers are fundamentally\ndifferent; currently, the intent is to manually check the diff images.  Passing\n``--tolerance=inf`` marks these tests as \"passed\" (while still textually\nreporting the image differences) so that one can spot issues not related to\nrendering differences.  In practice, ``--tolerance=50`` appears to be enough.\n\nSome other (non-image-comparison) tests are also known to fail (they are listed\nin ``ISSUES.rst``, with the relevant explanations), and automatically skipped.\n\nRun ``run-examples.py`` to run some examples that exercise some more aspects of\nmplcairo.\n\nNotes\n=====\n\nAntialiasing\n------------\n\nThe artist antialiasing property can be set to any of the ``cairo_antialias_t``\nenum values, or ``True`` (the default) or ``False`` (which is synonym to\n``NONE``).\n\nSetting antialiasing to ``True`` uses ``FAST`` antialiasing for lines thicker\nthan 1/3px and ``BEST`` for lines thinner than that: for lines thinner\nthan 1/3px, the former leads to artefacts such as lines disappearing in\ncertain sections (see e.g. ``test_cycles.test_property_collision_plot`` after\nforcing the antialiasing to ``FAST``).  The threshold of 1/3px was determined\nempirically, see `examples/thin_line_antialiasing.py`_.\n\n.. _examples/thin_line_antialiasing.py: examples/thin_line_antialiasing.py\n\nNote that in order to set the ``lines.antialiased`` or ``patch.antialiased``\nrcparams to a ``cairo_antialias_t`` enum value, it is necessary to bypass\nrcparam validation, using, e.g.\n\n.. code-block:: python\n\n   dict.__setitem__(plt.rcParams, \"lines.antialiased\", antialias_t.FAST)\n\nThe ``text.antialiased`` rcparam can likewise be set to any\n``cairo_antialias_t`` enum value, or ``True`` (the default, which maps to\n``SUBPIXEL`` \u2014 ``GRAY`` is not sufficient to benefit from Raqm_'s subpixel\npositioning; see also `cairo issue #152 <cairo-152_>`_) or ``False`` (which\nmaps to ``NONE``).\n\n.. _cairo-152: https://gitlab.freedesktop.org/cairo/cairo/issues/152\n\nNote that in rare cases, on cairo<1.17.4, ``FAST`` antialiasing can trigger a\n\"double free or corruption\" bug in cairo (`#44 <cairo-44_>`_).  If you hit this\nproblem, consider using ``BEST`` or ``NONE`` antialiasing (depending on your\nquality and speed requirements).\n\n.. _cairo-44: https://gitlab.freedesktop.org/cairo/cairo/issues/44\n\nFast drawing\n------------\n\nFor fast drawing of path with many segments, the ``agg.path.chunksize`` rcparam\nshould be set to e.g. 1000 (see `examples/time_drawing_per_element.py`_ for the\ndetermination of this value); this causes longer paths to be split into\nindividually rendered sections of 1000 segments each (directly rendering longer\npaths appears to have slightly superlinear complexity).\n\n.. _examples/time_drawing_per_element.py: examples/time_drawing_per_element.py\n\nSimplification threshold\n------------------------\n\nThe ``path.simplify_threshold`` rcparam is used to control the accuracy of\nmarker stamping, down to an arbitrarily chosen threshold of 1/16px.  If the\nthreshold is set to a lower value, the exact (slower) marker drawing path will\nbe used.  Marker stamping is also implemented for scatter plots (which can have\nmultiple colors).  Likewise, markers of different sizes get mapped into markers\nof discretized sizes, with an error bounded by the threshold.\n\n**NOTE**: ``pcolor`` and mplot3d's ``plot_surface`` display some artefacts\nwhere the facets join each other.  This is because these functions internally\nuse a ``PathCollection``; this triggers the approximate stamping, and\neven without it (by setting ``path.simplify_threshold`` to zero), cairo's\nrasterization of the edge between the facets is poor.  ``pcolormesh`` (which\ninternally uses a ``QuadMesh``) should generally be preferred over ``pcolor``\nanyways.  ``plot_surface`` could likewise instead represent the surface using\n``QuadMesh``, which is drawn without such artefacts.\n\nFont formats and features\n-------------------------\n\nIn order to use a specific font that Matplotlib may be unable to use, pass a\nfilename directly:\n\n.. code-block:: python\n\n   from matplotlib.font_manager import FontProperties\n   fig.text(.5, .5, \"hello, world\",\n            fontproperties=FontProperties(fname=\"/path/to/font.ttf\"))\n\nor more simply, with Matplotlib\u22653.3:\n\n.. code-block:: python\n\n   from pathlib import Path\n   fig.text(.5, .5, \"hello, world\", font=Path(\"/path/to/font.ttf\"))\n\nmplcairo still relies on Matplotlib's font cache, so fonts unsupported by\nMatplotlib remain unavailable by other means.\n\nFor TTC fonts (and, more generally, font formats that include multiple font\nfaces in a single file), the *n*\\th font (*n*\\\u22650) can be selected by appending\n``#n`` to the filename (e.g., ``\"/path/to/font.ttc#1\"``).\n\nOpenType font features can be selected by appending ``|feature,...``\nto the filename, followed by a `HarfBuzz feature string`_ (e.g.,\n``\"/path/to/font.otf|frac,onum\"``); see `examples/opentype_features.py`_.  A\nlanguage_ tag can likewise be set with ``|language=...``; currently, this\nalways applies to the whole buffer, but a PR adding support for slicing syntax\n(similar to font features) would be considered.\n\nOpenType font variations can be selected by appending an additional ``|`` to\nthe filename, followed by a `Cairo font variation string`_ (e.g.,\n``\"/path/to/font.otf||wdth=75\"``); see `examples/opentype_variations.py`_. This\nsupport requires Cairo>=1.16. Note that features are parsed first, so if you do\nnot wish to specify any features, you must specify an empty set with two pipes,\ni.e., ``font.otf|variations`` will treat ``variations`` as features, *not*\nvariations.\n\n.. _HarfBuzz feature string: https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-feature-from-string\n.. _Cairo font variation string: https://www.cairographics.org/manual/cairo-cairo-font-options-t.html#cairo-font-options-set-variations\n.. _language: https://host-oman.github.io/libraqm/raqm-Raqm.html#raqm-set-language\n\nThe syntaxes for selecting TTC subfonts and OpenType font features and language\ntags are **experimental** and may change, especially if such features are\nimplemented in Matplotlib itself.\n\nColor fonts (e.g. emojis) are handled.\n\nMulti-page output\n-----------------\n\nMatplotlib's ``PdfPages`` class is deeply tied with the builtin ``backend_pdf``\n(in fact, it cannot even be used with Matplotlib's own cairo backend).\nInstead, use ``mplcairo.multipage.MultiPage`` for multi-page PDF and PS output.\nThe API is similar:\n\n.. code-block:: python\n\n   from mplcairo.multipage import MultiPage\n\n   fig1 = ...\n   fig2 = ...\n   with MultiPage(path_or_stream, metadata=...) as mp:\n       mp.savefig(fig1)\n       mp.savefig(fig2)\n\nSee the class' docstring for additional information.\n\nVersion control for vector formats\n----------------------------------\n\ncairo is able to write PDF 1.4 and 1.5 (defaulting to 1.5), PostScript levels 2\nand 3 (defaulting to 3), and SVG versions 1.1 and 1.2 (defaulting to 1.1).\nThis can be controlled by passing a *metadata* dict to ``savefig`` with a\n``MaxVersion`` entry, which must be one of the strings ``\"1.4\"``/``\"1.5\"`` (for\npdf), ``\"2\"``/``\"3\"`` (for ps), or ``\"1.1\"``/``\"1.2\"`` (for svg).\n\n``cairo-script`` output\n-----------------------\n\nSetting the ``MPLCAIRO_SCRIPT_SURFACE`` environment variable *before mplcairo\nis imported* to ``vector`` or ``raster`` allows one to save figures (with\n``savefig``) in the ``.cairoscript`` format, which is a \"native script that\nmatches the cairo drawing model\".  The value of the variable determines the\nrendering path used (e.g., whether marker stamping is used at all).  This may\nbe helpful for troubleshooting purposes.\n\nNote that cairo-script output is generally broken on cairo\u22641.17.8.\n\nMarkers at B\u00e9zier control points\n--------------------------------\n\n``draw_markers`` draws a marker at each control point of the given path, which\nis the documented behavior, even though all builtin renderers only draw markers\nat straight or B\u00e9zier segment ends.\n\nKnown differences\n=================\n\nDue to missing support from cairo:\n\n- SVG output does not support global metadata or set URLs or ids on any\n  element, as cairo provides no support to do so.\n- PS output does not respect SOURCE_DATE_EPOCH.\n- PS output does not support the ``Creator`` metadata key; however it supports\n  the ``Title`` key.\n- The following rcparams have no effect:\n\n  - ``pdf.fonttype`` (font type is selected by cairo internally),\n  - ``pdf.inheritcolor`` (effectively always ``False``),\n  - ``pdf.use14corefonts`` (effectively always ``False``),\n  - ``ps.fonttype`` (font type is selected by cairo internally),\n  - ``ps.useafm`` (effectively always ``False``),\n  - ``svg.fonttype`` (effectively always ``\"path\"``, see `cairo issue #253\n    <cairo-253_>`_),\n  - ``svg.hashsalt``.\n\nAdditionally, the ``quality``, ``optimize``, and ``progressive`` parameters to\n``savefig``, which have been removed in Matplotlib 3.5, are not supported.\n\n.. _cairo-253: https://gitlab.freedesktop.org/cairo/cairo/issues/253\n\nPossible optimizations\n======================\n\n- Cache eviction policy and persistent cache for ``draw_path_collection``.\n- Use QtOpenGLWidget and the cairo-gl backend.\n\nWhat about the already existing cairo (gtk/qt/wx/tk/...cairo) backends?\n=============================================================================\n\nThey are very slow (try running `examples/mplot3d/wire3d_animation.py`_) and\nrender math poorly (try ``title(r\"$\\sqrt{2}$\")``).\n\n.. _examples/mplot3d/wire3d_animation.py: examples/mplot3d/wire3d_animation.py\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A (new) cairo backend for Matplotlib.",
    "version": "0.6.1",
    "project_urls": null,
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "61685868b26a7ae3a664e68ad33a4b3946678e66f77331dd546bb4a0aa48b163",
                "md5": "7bd60a3faa6182487f21d5c6e9ea95b2",
                "sha256": "eb4616787c4996b93fc4be77e8893e86dc4af0489fd03bf92e7c14ede4c6ed97"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp310-cp310-macosx_10_13_x86_64.whl",
            "has_sig": false,
            "md5_digest": "7bd60a3faa6182487f21d5c6e9ea95b2",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 344059,
            "upload_time": "2024-11-11T22:56:04",
            "upload_time_iso_8601": "2024-11-11T22:56:04.579619Z",
            "url": "https://files.pythonhosted.org/packages/61/68/5868b26a7ae3a664e68ad33a4b3946678e66f77331dd546bb4a0aa48b163/mplcairo-0.6.1-cp310-cp310-macosx_10_13_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fcc09a818d0403e67330832acc08cbee5b768330e58f3cc726db4ae2854d0664",
                "md5": "39964767bf716e6b01ddf10e3de450b8",
                "sha256": "a4a10e20aa8eda7200abc9849cc9d2e5b5726a728bb951bdee8a54b63433dc03"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "39964767bf716e6b01ddf10e3de450b8",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 1351608,
            "upload_time": "2024-11-11T22:56:07",
            "upload_time_iso_8601": "2024-11-11T22:56:07.039001Z",
            "url": "https://files.pythonhosted.org/packages/fc/c0/9a818d0403e67330832acc08cbee5b768330e58f3cc726db4ae2854d0664/mplcairo-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "531e863f3ef2cf40c71b9a4009ebcb2cfe76beab2bbcd6ba20ffb4bb086b2d94",
                "md5": "42182ddf3e24ebca62c4a9dc6d608265",
                "sha256": "3c1b7868b6b33ee5b5ec5bd2df2a7a125c1e8ca80cad2d74e8a20c0fbde99efd"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp310-cp310-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "42182ddf3e24ebca62c4a9dc6d608265",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 1782262,
            "upload_time": "2024-11-11T22:56:09",
            "upload_time_iso_8601": "2024-11-11T22:56:09.249830Z",
            "url": "https://files.pythonhosted.org/packages/53/1e/863f3ef2cf40c71b9a4009ebcb2cfe76beab2bbcd6ba20ffb4bb086b2d94/mplcairo-0.6.1-cp310-cp310-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "122760a504541cfa4d1338905a69a5d506ce95dbc1c9c895df21dfeb6fe8d485",
                "md5": "33e541e9a28e681e7baa663c8e86d9dc",
                "sha256": "9e3896053cb0443616119298c590d087b25a71452a099853049a9d26ffda8f48"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp311-cp311-macosx_10_13_universal2.whl",
            "has_sig": false,
            "md5_digest": "33e541e9a28e681e7baa663c8e86d9dc",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 648717,
            "upload_time": "2024-11-11T22:56:11",
            "upload_time_iso_8601": "2024-11-11T22:56:11.252927Z",
            "url": "https://files.pythonhosted.org/packages/12/27/60a504541cfa4d1338905a69a5d506ce95dbc1c9c895df21dfeb6fe8d485/mplcairo-0.6.1-cp311-cp311-macosx_10_13_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "eb69c1a0b9c37811e6caa3ff9101a743b5e1e52badd4e5f1e3e8064e34009e31",
                "md5": "816445ceb60b4ef5a6c258e05107a4b7",
                "sha256": "0664ab68744b78228b6c38b4be301bcd0e864b23a2f7c8472e020c8daab5210b"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "816445ceb60b4ef5a6c258e05107a4b7",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 1350184,
            "upload_time": "2024-11-11T22:56:13",
            "upload_time_iso_8601": "2024-11-11T22:56:13.365662Z",
            "url": "https://files.pythonhosted.org/packages/eb/69/c1a0b9c37811e6caa3ff9101a743b5e1e52badd4e5f1e3e8064e34009e31/mplcairo-0.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5529819040ad9d660fca50b4139c1f140b68fbea7e1716ffbfdba25c01a21ebd",
                "md5": "063224520b7d53943ea90266c0653a82",
                "sha256": "5849c849db22526b330f3b34a0100e8febe764dc043ba1e5667d33c725356f7c"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp311-cp311-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "063224520b7d53943ea90266c0653a82",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 1783106,
            "upload_time": "2024-11-11T22:56:14",
            "upload_time_iso_8601": "2024-11-11T22:56:14.979875Z",
            "url": "https://files.pythonhosted.org/packages/55/29/819040ad9d660fca50b4139c1f140b68fbea7e1716ffbfdba25c01a21ebd/mplcairo-0.6.1-cp311-cp311-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "895d141c35306da22994c3a39cebba1eebe0f5e4e36e94c8221034e88de8c6b3",
                "md5": "17feed28ea3acad2aaf5cb861df5d268",
                "sha256": "ea23c0c65ddf402d605ebf8917620284eb003f8e7a20f43f8c1459ee5a0a661e"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp312-cp312-macosx_10_13_universal2.whl",
            "has_sig": false,
            "md5_digest": "17feed28ea3acad2aaf5cb861df5d268",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 654076,
            "upload_time": "2024-11-11T22:56:16",
            "upload_time_iso_8601": "2024-11-11T22:56:16.383530Z",
            "url": "https://files.pythonhosted.org/packages/89/5d/141c35306da22994c3a39cebba1eebe0f5e4e36e94c8221034e88de8c6b3/mplcairo-0.6.1-cp312-cp312-macosx_10_13_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ccb2c4cfa9796e73227205a98e82a68ad5af85c858848ee50752c4c1fcd8ef66",
                "md5": "28a7558f40ec3e615a00d1c6753105df",
                "sha256": "351046cc6c6ed4f37031947dc88a4bfb104dff474631b1cfa6ee7274e9a6031d"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "28a7558f40ec3e615a00d1c6753105df",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 1351436,
            "upload_time": "2024-11-11T22:56:17",
            "upload_time_iso_8601": "2024-11-11T22:56:17.733732Z",
            "url": "https://files.pythonhosted.org/packages/cc/b2/c4cfa9796e73227205a98e82a68ad5af85c858848ee50752c4c1fcd8ef66/mplcairo-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fba5908f2fc1a1a463a2731be75aea5e67165b5597c91471978f95d01cc32a74",
                "md5": "0a863e83d5eb715d80fe399fea7b1f59",
                "sha256": "7a451d3c9b287a6a9b15d9131ab9574c86c219608a0401974d55c0340a82f8ca"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp312-cp312-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "0a863e83d5eb715d80fe399fea7b1f59",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 1784685,
            "upload_time": "2024-11-11T22:56:19",
            "upload_time_iso_8601": "2024-11-11T22:56:19.833080Z",
            "url": "https://files.pythonhosted.org/packages/fb/a5/908f2fc1a1a463a2731be75aea5e67165b5597c91471978f95d01cc32a74/mplcairo-0.6.1-cp312-cp312-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "901a6abac6f9ddb9184a5ab341383e56c38ea6afd4a2d5f84b9f292d3b5a1960",
                "md5": "3bca6fca3f300072cb2f3607e4340585",
                "sha256": "aa86452e3b895e431928c20d97f830903a076e6ab7c6df40ecc5a5eb055349b3"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp313-cp313-macosx_10_13_universal2.whl",
            "has_sig": false,
            "md5_digest": "3bca6fca3f300072cb2f3607e4340585",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 654221,
            "upload_time": "2024-11-11T22:56:22",
            "upload_time_iso_8601": "2024-11-11T22:56:22.003400Z",
            "url": "https://files.pythonhosted.org/packages/90/1a/6abac6f9ddb9184a5ab341383e56c38ea6afd4a2d5f84b9f292d3b5a1960/mplcairo-0.6.1-cp313-cp313-macosx_10_13_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "dcd9f3edd122e2df1cdb35cad6ac23ef2e51b74aef92836ac84497192ead5cc9",
                "md5": "924b19f306f4b7d1b60c8e98416ada75",
                "sha256": "1feb86c96201b492be8a6f655212942630e997f940e7d9600f549d09da02fb87"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "924b19f306f4b7d1b60c8e98416ada75",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 1351656,
            "upload_time": "2024-11-11T22:56:24",
            "upload_time_iso_8601": "2024-11-11T22:56:24.398205Z",
            "url": "https://files.pythonhosted.org/packages/dc/d9/f3edd122e2df1cdb35cad6ac23ef2e51b74aef92836ac84497192ead5cc9/mplcairo-0.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "185560c897bafbd4ba30b09670f63a9ef2ded590114f20a60b79397536a7ba84",
                "md5": "f8b9c02f6cb26050921d50abd3e50490",
                "sha256": "766aed941791e25ce8809aafc007fefe58603dc91e427934068315babd700ada"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp313-cp313-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "f8b9c02f6cb26050921d50abd3e50490",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 1784744,
            "upload_time": "2024-11-11T22:56:26",
            "upload_time_iso_8601": "2024-11-11T22:56:26.434705Z",
            "url": "https://files.pythonhosted.org/packages/18/55/60c897bafbd4ba30b09670f63a9ef2ded590114f20a60b79397536a7ba84/mplcairo-0.6.1-cp313-cp313-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "edc3d33019a8add63c113f3dfb0093413b81c285803d707fad4cb02d52f9240d",
                "md5": "5579500cb67bc7c05be3f54308c692de",
                "sha256": "856f302a8832cd24116880cd8cc6e20309b387ba713b17339bd968404b88af45"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp38-cp38-macosx_10_13_x86_64.whl",
            "has_sig": false,
            "md5_digest": "5579500cb67bc7c05be3f54308c692de",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 343840,
            "upload_time": "2024-11-11T22:56:27",
            "upload_time_iso_8601": "2024-11-11T22:56:27.674234Z",
            "url": "https://files.pythonhosted.org/packages/ed/c3/d33019a8add63c113f3dfb0093413b81c285803d707fad4cb02d52f9240d/mplcairo-0.6.1-cp38-cp38-macosx_10_13_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "987da66c24e1a2801500d5c648a5ab35e2e49d9c4beb3b5a0cf98e4f381c8797",
                "md5": "0dc51170e0d468bd7b3dd5d9666fe507",
                "sha256": "64fe49b09040709b4e70e16e89977ca30e5778047ca8c75928ff34982c02825e"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "0dc51170e0d468bd7b3dd5d9666fe507",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 1351021,
            "upload_time": "2024-11-11T22:56:29",
            "upload_time_iso_8601": "2024-11-11T22:56:29.535600Z",
            "url": "https://files.pythonhosted.org/packages/98/7d/a66c24e1a2801500d5c648a5ab35e2e49d9c4beb3b5a0cf98e4f381c8797/mplcairo-0.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "63935379c0cff063c957a8070d4aa1ee4de32262605557a8860ecc02c7277b54",
                "md5": "93ebf77d4ff12c6d927ea9d226091d63",
                "sha256": "398dde54a85d6ced839dc236c5bb41b8af4d46a669ae08cbb0c665ce774babb7"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp38-cp38-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "93ebf77d4ff12c6d927ea9d226091d63",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 1782313,
            "upload_time": "2024-11-11T22:56:31",
            "upload_time_iso_8601": "2024-11-11T22:56:31.599382Z",
            "url": "https://files.pythonhosted.org/packages/63/93/5379c0cff063c957a8070d4aa1ee4de32262605557a8860ecc02c7277b54/mplcairo-0.6.1-cp38-cp38-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "90aedf1746d60ed179a012544976a9855a69882ffc016b87ed94d1ae85a93c4b",
                "md5": "1e3543e1457213de2c839ba911d7763e",
                "sha256": "71b88c91ebe5deda83809083e8871dea32bf149697a1c5212df4d8ae5104d83f"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp39-cp39-macosx_10_13_x86_64.whl",
            "has_sig": false,
            "md5_digest": "1e3543e1457213de2c839ba911d7763e",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.8",
            "size": 344208,
            "upload_time": "2024-11-11T22:56:33",
            "upload_time_iso_8601": "2024-11-11T22:56:33.532052Z",
            "url": "https://files.pythonhosted.org/packages/90/ae/df1746d60ed179a012544976a9855a69882ffc016b87ed94d1ae85a93c4b/mplcairo-0.6.1-cp39-cp39-macosx_10_13_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fcc4102be31ace72b08e4f13935dfc53df94b79c72c0adb23416d271b409d467",
                "md5": "ae7ceae22f3781f0b24451caed1dadde",
                "sha256": "e78d1c8770e0daaef93960b4bd35143c536cec2ac77a612ceeb6fb0353710492"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "ae7ceae22f3781f0b24451caed1dadde",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.8",
            "size": 1352248,
            "upload_time": "2024-11-11T22:56:35",
            "upload_time_iso_8601": "2024-11-11T22:56:35.172416Z",
            "url": "https://files.pythonhosted.org/packages/fc/c4/102be31ace72b08e4f13935dfc53df94b79c72c0adb23416d271b409d467/mplcairo-0.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8c2a18dfbd001f816d439359e50abea114b6be06f99a7a2df7bb5d8d07c718c7",
                "md5": "81945e2cfb5df0fd2866bb23f22e96ce",
                "sha256": "263f77ac751af375692cc96e9c2e6cd47951c9470e650963f8d71d11273dacb0"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1-cp39-cp39-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "81945e2cfb5df0fd2866bb23f22e96ce",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.8",
            "size": 1778762,
            "upload_time": "2024-11-11T22:56:37",
            "upload_time_iso_8601": "2024-11-11T22:56:37.179319Z",
            "url": "https://files.pythonhosted.org/packages/8c/2a/18dfbd001f816d439359e50abea114b6be06f99a7a2df7bb5d8d07c718c7/mplcairo-0.6.1-cp39-cp39-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1fd62d24fc6152db8161075b18070eda687b9c5c2428980b309184fb0653fab6",
                "md5": "2633fc08f36a3dd2a06da44279a7a369",
                "sha256": "eac1d408cf4101db0ab4d0d57e6c3840bd5434818dc6cd295fc923062f9180d5"
            },
            "downloads": -1,
            "filename": "mplcairo-0.6.1.tar.gz",
            "has_sig": false,
            "md5_digest": "2633fc08f36a3dd2a06da44279a7a369",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 97657,
            "upload_time": "2024-11-11T22:56:39",
            "upload_time_iso_8601": "2024-11-11T22:56:39.169571Z",
            "url": "https://files.pythonhosted.org/packages/1f/d6/2d24fc6152db8161075b18070eda687b9c5c2428980b309184fb0653fab6/mplcairo-0.6.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-11 22:56:39",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "mplcairo"
}
        
Elapsed time: 0.83463s