Using Sphinx Extension to convert svg to pdf
Asked Answered
A

2

6

My company is using Sphinx to create the manuals for our products. Our products are shipped with PDF and HTML documentations. We are using Windows as a sole developer environment.

A necessary requirement is to generate both kind of format from the same sources (*.rst files).

A legacy documentation uses extensive SVG-Images, but the sphinx build format latex does not support SVG-Files in \includegraphics{} environments.

Now I found the promising Sphinx-Extension sphinx.ext.imgconverter and included it into my conf.py.

extensions = [
    'sphinx.ext.imgmath',
    'sphinx.ext.ifconfig',
    'sphinx.ext.imgconverter'
]

Hopefully, converting all SVG-Files into PDF-files if I'm building LaTeX. Unfortunately, the documentation of the extension is very short and there is no working example.

http://www.sphinx-doc.org/en/master/ext/imgconverter.html#module-sphinx.ext.imgconverter

The contents of our rst files are basically:

.. image:: Image.*
   :width: 100px

Sphinx should figure out on its own, if the star should be replcaced by svg or pdf depending on the build html/pdf. This information I got from previous posts:

  1. Using Sphinx docs how can I specify png image formats for HTML builds and pdf image formats for Latex/PDF builds?

But somehow there I'm unable to generate my latex. Using Sphinx docs how can I specify png image formats for HTML builds and pdf image formats for Latex/PDF builds?

Instead the following warning is issued:

WARNING: no matching candidate for image URI u'Image.*'

But only if I wanted to build LaTeX in case of HTML there is no warning.

Do I have to install ImageMagick or is there is something wrong? How does Sphinx know, where to search ImageMagick?

Update

I just updated my Sphinx to version 1.7.2. It still doesn't work. As I was unable to install ImageMagick, I temporarily removed the extension sphinx.ext.imgconverter from my conf.py to test for a manual solution. I converted all the images manually to pdf/png using inkscape.

Now I got the following warnings, if I compile with make latex.

WARNING: a suitable image for latex builder not found: ['image/svg+xml']

But there are definitely manually converted images (pdf,png) in both the source directory and the build/latex directory, alike.

My LaTeX file is compiled to something like:

\noindent\sphinxincludegraphics[width=100\sphinxpxdimen]{{Image}.*}

And I'm unable to compile it with pdflatex.

LaTeX Error: Unknown graphics extension: .*.

Are there some settings for the LaTeX Builder in my conf.py to take my converted images?

If I include the following lines in my conf.py something unexpected happens:

from sphinx.builders.latex import LaTeXBuilder
LaTeXBuilder.supported_image_types = ['image/png', 'image/pdf','image/svg+xml' ]

The output of my LaTeX file now contains the line:

\noindent\sphinxincludegraphics[width=100\sphinxpxdimen]{{Image}.svg}

If I remove the type image/svg+xml from the supported_image_types I got the previous error again. My impression is, that sphinx-build looks for the converted images in the wrong places. But this is just an idea.

Aholah answered 18/4, 2018 at 11:39 Comment(1)
check out sphinxcontrib-svg2pdfconverter which will help convert on the fly svg's to pdf's for usage with latex builder of Sphinx. It is based on sphinx.ext.imgconverter to add conversion via inkscape or rsvg-convertCallaway
L
4

Scaling scholars select svg2pdfconverter

If you want really high-quality embedded images in your Sphinx-latexpdf-generated documents, @user4184837's suggestion of using sphinx-svg2pdfconverter is absolutely the way to go, because it does Just What It Says On The Tin™: It converts your SVG files to small embeddable PDF documents which retain their scalability! The vectors never get rasterized anywhere in the output pipeline, so they're sharp and clear at any size.

Installation and selection of rendering backend

To get the Sphinx extension you can just pip install sphinxcontrib-svg2pdfconverter, but you'll also need an SVG interpreter/converter backend. (The extension only handles the Sphinx end of things.) Currently, three are supported:

  1. Inkscape, which requires you to install... well... all of Inkscape.
  2. The rsvg-convert command-line tool, which can be installed from the appropriate distro package on Linux, or acquired by other means. (The package is spelled librsvg2-bin in the Debian universe, whereas those more partial to crimson headwear pronounce it librsvg2-tools.)
  3. Lightest-weight of all, you can just install cairosvg, a Python package you can just install from PyPi at the same time as the extension itself. Svg2pdfconverter has a couple of additional dependencies when using Cairosvg, so you'll want to install it as sphinxcontrib-svg2pdfconverter[Cairosvg].

At least for my relatively simple graphics of toolbar-icon-level complexity, the choice of backend makes no discernible difference in the output. So, obviously Cairosvg is the path of least resistance there. It's as simple as inserting it into your list of Python package dependencies.

Cairosvg isn't actually implemented exclusively in Python, but it is a pure-Python PyPi package. As the name implies, it's based on Cairo, and uses cffi to dlopen() and interface with an available libcairo.so / libcairo.dylib / libcairo.dll.

Cairosvg won't install libcairo if you don't have it, but it's pretty ubiquitous:

  • It's hard to find a Linux system without cairo as a system package.
  • On macOS, it picked up an existing /usr/local/lib/libcairo.dylib; Homebrew says it was installed as a dependency of ffmpeg. And opencv. And gtk+3. And...
  • Windows is slightly harder, but if you've installed MSYS2 you already have a libcairo.dll in C:\msys64\mingw64\bin\. Even in cmd.exe/pwsh.exe, add that dir to your path and cairosvg will pick up the DLL.

You can confirm it sees the library by just importing its cffi interface:

>>> import cairocffi
>>> # If you DON'T see any error messages, you're good to go
>>> # or confirm and check the library location with...
>>> cairocffi.cairo
<Lib object for '/usr/local/lib/libcairo.dylib'>

Putting it all together

There is some configuration possible with svg2pdfconverter, but it's very likely you won't need it, at least initially. It absolutely will just work right out of the box, with zero config beyond adding it to the extensions list in your conf.py.

You choose the backend to use by the extension class you add:

  • sphinxcontrib.inkscapeconverter
  • sphinxcontrib.rsvgconverter
  • sphinxcontrib.cairosvgconverter

Pick the one you have the necessary dependencies for, and you're off to the races.

More likely what you'll need to adjust are your SVG files, slightly, so that they're better suited to embedding in your Sphinx documents.

I hate to break it to you, but: size matters

The first issue is layout — if you want to place SVG images inline with your text content, you'll need to scale and frame them accordingly. A 16px square icon is probably the maximum size you'd want to use inline, and evne that's going to overpower the surrounding text a bit. If you import a 128px square icon design instead, it will be proportionally eight times larger, and your body text will be interrupted by a dropped-in graphic that takes up nearly half the page.

You'll probably also want to design inline SVG images so they're aligned to the very bottom center of their bounding box, with a fair amount of space remaining above. An inline embedded SVG sits directly on the text baseline, extending only upward as its size increases. So any padding below just makes it look even more awkward, while you need padding above because the top of the image's bounding box will dictate the height of that line of text.

When I originally imported the SVG icons for our documentation (well, after I re-imported them, scaled down from 256px square to 16px!) they all had shrink-wrapped bounding boxes. In the final PDF every SVG image that ended up in the first line of text for a table cell was wearing the border line above it for a hat.

Realigning the graphics so they were roughly 12px wide by no taller than 14px, sitting at the bottom of a 16px square page area:

plus-sign icon laid out on an Inkscape canvas, with empty space on three sides, but no gap along the bottom edge

...created a little breathing room:

zoomed-in detail of a rendered PDF, showing text with an SVG icon embedded inline

And that's pretty much that!

Lillis answered 5/1, 2022 at 8:25 Comment(0)
I
1
  1. I suspect that the error is related to this issue. It was fixed in Sphinx 1.7, which indicates you have a release of Sphinx < 1.7 installeed. Upgrade to Sphinx 1.7 or greater. Tip: always search the source code repository for help.
  2. From the documentation for sphinx.ext.imgconverter:

    Internally, this extension uses Imagemagick to convert images.

    Which means it must be installed and be in your system path.

Infrangible answered 18/4, 2018 at 20:37 Comment(1)
Thanks for your suggestions. I have sphinx-build 1.7.0 installed. I'll try for updates.Aholah

© 2022 - 2025 — McMap. All rights reserved.