summaryrefslogtreecommitdiffstats
path: root/share/extensions/pdflatex.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/pdflatex.py')
-rwxr-xr-xshare/extensions/pdflatex.py139
1 files changed, 139 insertions, 0 deletions
diff --git a/share/extensions/pdflatex.py b/share/extensions/pdflatex.py
new file mode 100755
index 0000000..f989191
--- /dev/null
+++ b/share/extensions/pdflatex.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Copyright (C) 2019 Marc Jeanmougin
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+"""
+Generate Latex via a PDF using pdflatex
+"""
+
+import os
+
+import inkex
+from inkex.base import TempDirMixin
+from inkex.command import ProgramRunError, call, inkscape
+from inkex import load_svg, ShapeElement, Defs
+from inkex.units import convert_unit
+from inkex.localization import inkex_gettext as _
+
+
+class PdfLatex(TempDirMixin, inkex.GenerateExtension):
+ """
+ Use pdflatex to generate LaTeX, this whole hack is required because
+ we don't want to open a LaTeX document as a document, but as a
+ generated fragment (like import, but done manually).
+ """
+
+ def add_arguments(self, pars):
+ pars.add_argument(
+ "--formule",
+ type=str,
+ default=r"\(\displaystyle\frac{\pi^2}{6}=\lim_{n \to \infty}\sum_{k=1}^n \frac{1}{k^2}\)",
+ )
+ pars.add_argument(
+ "--preamble",
+ type=str,
+ default="".join(
+ f"\\usepackage{{ams{i}}}" for i in ["math", "symb", "fonts"]
+ ),
+ )
+ pars.add_argument("--font_size", type=int, default=10)
+ pars.add_argument("--page", choices=["basic", "advanced"])
+ pars.add_argument("--standalone", type=inkex.Boolean, default=True)
+
+ def generate(self):
+ tex_file = os.path.join(self.tempdir, "input.tex")
+ pdf_file = os.path.join(self.tempdir, "input.pdf") # Auto-generate by pdflatex
+ svg_file = os.path.join(self.tempdir, "output.svg")
+
+ with open(tex_file, "w") as fhl:
+ self.write_latex(fhl)
+
+ try:
+ call(
+ "pdflatex",
+ tex_file,
+ output_directory=self.tempdir,
+ halt_on_error=True,
+ oldie=True,
+ )
+ except ProgramRunError as err:
+ inkex.errormsg(_("An exception occurred during LaTeX compilation: ") + "\n")
+ inkex.errormsg(err.stdout.decode("utf8").replace("\r\n", "\n"))
+ raise inkex.AbortExtension()
+
+ inkscape(
+ pdf_file,
+ export_filename=svg_file,
+ pdf_page=1,
+ pdf_poppler=True,
+ export_type="svg",
+ actions=(
+ "select-all;page-fit-to-selection;"
+ "clone-unlink-recursively;vacuum-defs"
+ ),
+ )
+
+ if not os.path.isfile(svg_file):
+ fn = os.path.basename(svg_file)
+ if os.path.isfile(fn):
+ # Inkscape bug detected, file got saved wrong
+ svg_file = fn
+
+ with open(svg_file, "r") as fhl:
+ svg: inkex.SvgDocumentElement = load_svg(fhl).getroot()
+
+ scale = convert_unit("1pt", "px") / self.svg.scale
+ if not self.options.standalone:
+ scale *= self.options.font_size / 10
+
+ for child in svg:
+ if isinstance(child, ShapeElement):
+ child.transform = inkex.Transform(scale=scale) @ child.transform
+ yield child
+ elif isinstance(child, Defs):
+ for def_child in child:
+ # The ids of both the imported and the target document should
+ # be off-limits
+ def_child.set_random_ids(
+ backlinks=True, blacklist=self.svg.get_ids()
+ )
+ self.svg.defs.append(def_child)
+
+ def write_latex(self, stream):
+ """Takes a formula and wraps it in latex"""
+ if self.options.standalone:
+ docclass = (
+ f"\\documentclass[fontsize={self.options.font_size}pt, "
+ + "class=scrreprt, preview]{standalone}"
+ )
+ else:
+ docclass = r"\documentclass{minimal}"
+ stream.write(
+ f"""%% processed with pdflatex.py
+{docclass}
+{self.options.preamble}
+\\begin{{document}}
+{self.options.formule}
+\\end{{document}}
+"""
+ )
+ stream.flush()
+
+
+if __name__ == "__main__":
+ PdfLatex().run()