Replacement for the sphinx ``figure`` and ``images`` directive. A image (or figure) directive which make use of the *glob* notation:: .. figure:: hello.* 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> --- 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..50d63bd --- /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 node + 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 -- 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