On Sun, Nov 27, 2016 at 04:02:05PM +0100, Markus Heiser wrote: > Replacement for the sphinx ``figure`` and ``images`` directive. > > A image (or figure) directive which make use of the *glob* notation:: > > .. figure:: hello.* For namespacing, I think we should call this kernel-figure or something like that. Just to make it clear that this is our thing (like kernel-doc and kernel-include). > will be converted automatically with the tool chains listed below.: > > * DOT to SVG: ``DOT(1)`` (http://www.graphviz.org) If graphviz is not > available, the DOT language is inserted as literal-include. > > * SVG to PDF: > > * CairoSVG (http://cairosvg.org) if installed or alternatively > * ``convert(1)``: ImageMagick (https://www.imagemagick.org) > > Signed-off-by: Markus Heiser <markus.heiser@xxxxxxxxxxx> Otherwise exactly what I think we should have to make .dot/.svg images as easy to use as possible from a doc-writer pov. Together with Mauro's patch to auto-detect .dot/.svg files of course. Also comes with good docs itself, which is always great! Acked-by: Daniel Vetter <daniel.vetter@xxxxxxxx> > --- > Documentation/conf.py | 2 +- > Documentation/doc-guide/hello.dot | 3 + > Documentation/doc-guide/sphinx.rst | 18 ++++++ > Documentation/sphinx/figure.py | 123 +++++++++++++++++++++++++++++++++++++ > 4 files changed, 145 insertions(+), 1 deletion(-) > create mode 100644 Documentation/doc-guide/hello.dot > create mode 100644 Documentation/sphinx/figure.py > > diff --git a/Documentation/conf.py b/Documentation/conf.py > index 1ac958c..386d792 100644 > --- a/Documentation/conf.py > +++ b/Documentation/conf.py > @@ -34,7 +34,7 @@ from load_config import loadConfig > # Add any Sphinx extension module names here, as strings. They can be > # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom > # ones. > -extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain'] > +extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'figure'] > > # The name of the math extension changed on Sphinx 1.4 > if major == 1 and minor > 3: > diff --git a/Documentation/doc-guide/hello.dot b/Documentation/doc-guide/hello.dot > new file mode 100644 > index 0000000..504621d > --- /dev/null > +++ b/Documentation/doc-guide/hello.dot > @@ -0,0 +1,3 @@ > +graph G { > + Hello -- World > +} > diff --git a/Documentation/doc-guide/sphinx.rst b/Documentation/doc-guide/sphinx.rst > index 96fe7ccb..6f8fdd1 100644 > --- a/Documentation/doc-guide/sphinx.rst > +++ b/Documentation/doc-guide/sphinx.rst > @@ -217,3 +217,21 @@ Rendered as: > * .. _`last row`: > > - column 3 > + > +Figures > +======= > + > +If you want to add an image on either Graphviz or SVG format, you should > +use Sphinx ``figure``, where the name of the image file should end with > +``.*``, like:: > + > + .. figure:: hello.* > + :alt: hello world > + > + DOT's hello world example > + > + > +.. figure:: hello.* > + :alt: hello world > + > + DOT's hello world example > diff --git a/Documentation/sphinx/figure.py b/Documentation/sphinx/figure.py > new file mode 100644 > index 0000000..1aeeefa > --- /dev/null > +++ b/Documentation/sphinx/figure.py > @@ -0,0 +1,123 @@ > +# -*- coding: utf-8; mode: python -*- > +# pylint: disable=W0141,C0113,C0103,C0325 > +u""" > + images > + ~~~~~~ > + > + Replacement for the sphinx ``figure`` and ``images`` directive. > + > + :copyright: Copyright (C) 2016 Markus Heiser > + :license: GPL Version 2, June 1991 see Linux/COPYING for details. > + > + List of customizations: > + > + * generate PDF from SVG > + > + * generate SVG / PDF from DOT files, see > + http://www.graphviz.org/content/dot-language > + > + A image (or figure) directive which make use of the *glob* notation will be > + converted automatically with the tool chains listed below.: > + > + * DOT to SVG: ``DOT(1)`` (http://www.graphviz.org) If graphviz is not > + available, the DOT language is inserted as literal-include. > + > + * SVG to PDF: > + > + * CairoSVG (http://cairosvg.org) if installed or alternatively > + * ``convert(1)``: ImageMagick (https://www.imagemagick.org) > +""" > + > +import os > +from glob import glob > +import subprocess > + > +from docutils import nodes > +from docutils.parsers.rst import directives > +from docutils.parsers.rst.directives import images > + > +from sphinx.directives import patches > + > +try: > + import cairosvg > +except ImportError: > + cairosvg = None > + > +def cmd_exists(cmd): > + exit_code = subprocess.call( > + "type " + cmd, shell = True, > + stdout = subprocess.PIPE, stderr = subprocess.PIPE ) > + return bool(exit_code == 0) > + > +convert_exists = cmd_exists('convert') > +dot_exists = cmd_exists('dot') > + > +def setup(app): # pylint: disable=W0613 > + directives.register_directive('figure', Figure) > + directives.register_directive('image', Image) > + > +def asterix_conversions(folder, node): > + if not node['uri'].endswith('.*'): > + return True > + name = folder + os.path.sep + os.path.splitext(node['uri'])[0] > + > + fnames = glob(name + '.*') > + if (name + '.dot' in fnames): > + if not dot_exists: > + with open(name + '.dot', "r") as dot: > + data = dot.read() > + node = nodes.literal_block(data, data) > + else: > + dot2svg(name) > + > + fnames = glob(name + '.*') > + if (name + '.svg' in fnames): > + svg2pdf(name) > + return node > + > + > +def dot2svg(fname): > + cmd = "dot -Tsvg %s.dot" % fname > + with open(fname + '.svg', "w") as svg: > + exit_code = subprocess.call( > + cmd, shell = True, > + stdout = svg, > + stderr = subprocess.PIPE ) > + svg.flush() > + return bool(exit_code == 0) > + > +def svg2pdf(fname): > + > + if cairosvg: > + cairosvg.svg2pdf(url = fname + '.svg', write_to = fname + '.pdf') > + return True > + > + if convert_exists: > + cmd = "convert %s.svg %s.pdf" % (fname, fname) > + exit_code = subprocess.call( > + cmd, shell = True, > + stdout = subprocess.PIPE, stderr = subprocess.PIPE ) > + return bool(exit_code == 0) > + > + return False > + > +class Image(images.Image): > + > + def run(self): > + result = images.Image.run(self) > + if len(result) == 2 or isinstance(result[0], nodes.system_message): > + return result > + folder = os.path.dirname(self.state.document.current_source) > + result[0] = asterix_conversions(folder, result[0]) > + return result > + > +class Figure(patches.Figure): > + > + def run(self): > + result = patches.Figure.run(self) > + if len(result) == 2 or isinstance(result[0], nodes.system_message): > + return result > + folder = os.path.dirname(self.state.document.current_source) > + result[0][0] = asterix_conversions(folder, result[0][0]) > + return result > + > -- > 2.7.4 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html