Code

- change cmdline option to --export-latex.
authorJohan Engelen <goejendaagh@zonnet.nl>
Mon, 22 Feb 2010 19:33:37 +0000 (20:33 +0100)
committerJohan Engelen <goejendaagh@zonnet.nl>
Mon, 22 Feb 2010 19:33:37 +0000 (20:33 +0100)
- change source file names to reflect that it is "generic" latex renderer
- make latex export work for EPS and PS aswell

inkscape.pod
src/extension/internal/Makefile_insert
src/extension/internal/cairo-ps-out.cpp
src/extension/internal/cairo-renderer-pdf-out.cpp
src/extension/internal/latex-text-renderer.cpp [new file with mode: 0644]
src/extension/internal/latex-text-renderer.h [new file with mode: 0644]
src/extension/internal/pdflatex-renderer.cpp [deleted file]
src/extension/internal/pdflatex-renderer.h [deleted file]
src/main.cpp

index fed3dfb51c6c086599077b715d5c686fb88b9a43..52b76b4a9048097c003f9d600ed606832b1acfaa 100644 (file)
@@ -32,7 +32,7 @@ options:
     -P, --export-ps=FILENAME
     -E, --export-eps=FILENAME
     -A, --export-pdf=FILENAME
     -P, --export-ps=FILENAME
     -E, --export-eps=FILENAME
     -A, --export-pdf=FILENAME
-        --export-pdf-latex
+        --export-latex
 
     -T, --export-text-to-path
         --export-ignore-filters
 
     -T, --export-text-to-path
         --export-ignore-filters
@@ -268,13 +268,14 @@ The default export area is page; you can set it to drawing by --export-area-draw
 specify --export-id to export a single object (all other are hidden); in that case 
 export area is that object's bounding box, but can be set to page by --export-area-page.
 
 specify --export-id to export a single object (all other are hidden); in that case 
 export area is that object's bounding box, but can be set to page by --export-area-page.
 
-=item B<--export-pdf-latex>
+=item B<--export-latex>
 
 
+(for PS, EPS, and PDF export)
 Used for creating images for LaTeX documents, where the image's text is typeset by LaTeX.
 Used for creating images for LaTeX documents, where the image's text is typeset by LaTeX.
-When exporting to PDF format, this option splits the output into a PDF file 
-(as specified by --export-pdf) and a LaTeX file. Text will not be output in 
-the PDF file, but instead will appear in the LaTeX file. This LaTeX file 
-includes the PDF. Inputting (\input{image.tex}) the LaTeX file in your LaTeX
+When exporting to PDF/PS/EPS format, this option splits the output into a PDF/PS/EPS file 
+(e.g. as specified by --export-pdf) and a LaTeX file. Text will not be output in 
+the PDF/PS/EPS file, but instead will appear in the LaTeX file. This LaTeX file 
+includes the PDF/PS/EPS. Inputting (\input{image.tex}) the LaTeX file in your LaTeX
 document will show the image and all text will be typeset by LaTeX. See the
 resulting LaTeX file for more information.
 Also see GNUPlot's `epslatex' output terminal.
 document will show the image and all text will be typeset by LaTeX. See the
 resulting LaTeX file for more information.
 Also see GNUPlot's `epslatex' output terminal.
index 881b3ec22e6f723ae4f13cb7bd0d4f038b2fa110..3c1ce7f43da827ff06fe1d17a4120de24d7a6c89 100644 (file)
@@ -109,8 +109,8 @@ ink_common_sources +=       \
        extension/internal/javafx-out.h \
        extension/internal/gdkpixbuf-input.h    \
        extension/internal/gdkpixbuf-input.cpp  \
        extension/internal/javafx-out.h \
        extension/internal/gdkpixbuf-input.h    \
        extension/internal/gdkpixbuf-input.cpp  \
-       extension/internal/pdflatex-renderer.h \
-       extension/internal/pdflatex-renderer.cpp \
+       extension/internal/latex-text-renderer.h \
+       extension/internal/latex-text-renderer.cpp \
        extension/internal/pdfinput/svg-builder.h \
        extension/internal/pdfinput/svg-builder.cpp \
        extension/internal/pdfinput/pdf-parser.h \
        extension/internal/pdfinput/svg-builder.h \
        extension/internal/pdfinput/svg-builder.cpp \
        extension/internal/pdfinput/pdf-parser.h \
index 737bb2885a25cdcd6e261dd5a318a8694d4556af..6f22dbdc71d00b0569ff508b9e2faa4168593296 100644 (file)
@@ -21,6 +21,7 @@
 #include "cairo-ps-out.h"
 #include "cairo-render-context.h"
 #include "cairo-renderer.h"
 #include "cairo-ps-out.h"
 #include "cairo-render-context.h"
 #include "cairo-renderer.h"
+#include "latex-text-renderer.h"
 #include <print.h>
 #include "extension/system.h"
 #include "extension/print.h"
 #include <print.h>
 #include "extension/system.h"
 #include "extension/print.h"
@@ -61,7 +62,8 @@ bool CairoEpsOutput::check (Inkscape::Extension::Extension * /*module*/)
 }
 
 static bool
 }
 
 static bool
-ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false)
+ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool omittext,
+                          bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false)
 {
     sp_document_ensure_up_to_date(doc);
 
 {
     sp_document_ensure_up_to_date(doc);
 
@@ -93,6 +95,7 @@ ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int l
     ctx->setPSLevel(level);
     ctx->setEPS(eps);
     ctx->setTextToPath(texttopath);
     ctx->setPSLevel(level);
     ctx->setEPS(eps);
     ctx->setTextToPath(texttopath);
+    renderer->_omitText = omittext;
     ctx->setFilterToBitmap(filtertobitmap);
     ctx->setBitmapResolution(resolution);
 
     ctx->setFilterToBitmap(filtertobitmap);
     ctx->setBitmapResolution(resolution);
 
@@ -146,6 +149,14 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con
         new_textToPath  = mod->get_param_bool("textToPath");
     } catch(...) {}
 
         new_textToPath  = mod->get_param_bool("textToPath");
     } catch(...) {}
 
+    bool new_textToLaTeX  = FALSE;
+    try {
+        new_textToLaTeX  = mod->get_param_bool("textToLaTeX");
+    }
+    catch(...) {
+        g_warning("Parameter <textToLaTeX> might not exist");
+    }
+
     bool new_blurToBitmap  = FALSE;
     try {
         new_blurToBitmap  = mod->get_param_bool("blurToBitmap");
     bool new_blurToBitmap  = FALSE;
     try {
         new_blurToBitmap  = mod->get_param_bool("blurToBitmap");
@@ -171,13 +182,29 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con
         new_exportId = mod->get_param_string("exportId");
     } catch(...) {}
 
         new_exportId = mod->get_param_string("exportId");
     } catch(...) {}
 
-       gchar * final_name;
-       final_name = g_strdup_printf("> %s", filename);
-       ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage);
-       g_free(final_name);
+    // Create PS
+    {
+        gchar * final_name;
+        final_name = g_strdup_printf("> %s", filename);
+        ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage);
+        g_free(final_name);
 
 
-       if (!ret)
-           throw Inkscape::Extension::Output::save_failed();
+        if (!ret)
+            throw Inkscape::Extension::Output::save_failed();
+    }
+
+    // Create LaTeX file (if requested)
+    if (new_textToLaTeX) {
+        gchar * tex_filename;
+        //strip filename of ".ps", do not add ".tex" here.
+        gsize n = g_str_has_suffix(filename, ".ps") ? strlen(filename)-3 : strlen(filename);
+        tex_filename = g_strndup(filename, n);
+        ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage);
+        g_free(tex_filename);
+
+        if (!ret)
+            throw Inkscape::Extension::Output::save_failed();
+    }
 }
 
 
 }
 
 
@@ -210,6 +237,14 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co
         new_textToPath  = mod->get_param_bool("textToPath");
     } catch(...) {}
 
         new_textToPath  = mod->get_param_bool("textToPath");
     } catch(...) {}
 
+    bool new_textToLaTeX  = FALSE;
+    try {
+        new_textToLaTeX  = mod->get_param_bool("textToLaTeX");
+    }
+    catch(...) {
+        g_warning("Parameter <textToLaTeX> might not exist");
+    }
+
     bool new_blurToBitmap  = FALSE;
     try {
         new_blurToBitmap  = mod->get_param_bool("blurToBitmap");
     bool new_blurToBitmap  = FALSE;
     try {
         new_blurToBitmap  = mod->get_param_bool("blurToBitmap");
@@ -235,13 +270,29 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co
         new_exportId = mod->get_param_string("exportId");
     } catch(...) {}
 
         new_exportId = mod->get_param_string("exportId");
     } catch(...) {}
 
-       gchar * final_name;
-       final_name = g_strdup_printf("> %s", filename);
-       ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage, true);
-       g_free(final_name);
+    // Create EPS
+    {
+        gchar * final_name;
+        final_name = g_strdup_printf("> %s", filename);
+        ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage, true);
+        g_free(final_name);
 
 
-       if (!ret)
-           throw Inkscape::Extension::Output::save_failed();
+        if (!ret)
+            throw Inkscape::Extension::Output::save_failed();
+    }
+
+    // Create LaTeX file (if requested)
+    if (new_textToLaTeX) {
+        gchar * tex_filename;
+        //strip filename of ".eps", do not add ".tex" here.
+        gsize n = g_str_has_suffix(filename, ".eps") ? strlen(filename)-4 : strlen(filename);
+        tex_filename = g_strndup(filename, n);
+        ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage);
+        g_free(tex_filename);
+
+        if (!ret)
+            throw Inkscape::Extension::Output::save_failed();
+    }
 }
 
 
 }
 
 
@@ -280,6 +331,7 @@ CairoPsOutput::init (void)
 #endif
             "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
 #endif
             "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
+                       "<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
@@ -317,6 +369,7 @@ CairoEpsOutput::init (void)
 #endif
             "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
 #endif
             "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
+                       "<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
index 594389c60f7f83cf6e7dba105d5c7172c0f8f2bb..1dcfbdf1d746d94e0ff5772505e380f7d5786f70 100644 (file)
@@ -5,8 +5,9 @@
  * Authors:
  *   Ted Gould <ted@gould.cx>
  *   Ulf Erikson <ulferikson@users.sf.net>
  * Authors:
  *   Ted Gould <ted@gould.cx>
  *   Ulf Erikson <ulferikson@users.sf.net>
+ *   Johan Engelen <goejendaagh@zonnet.nl>
  *
  *
- * Copyright (C) 2004-2006 Authors
+ * Copyright (C) 2004-2010 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -20,7 +21,7 @@
 #include "cairo-renderer-pdf-out.h"
 #include "cairo-render-context.h"
 #include "cairo-renderer.h"
 #include "cairo-renderer-pdf-out.h"
 #include "cairo-render-context.h"
 #include "cairo-renderer.h"
-#include "pdflatex-renderer.h"
+#include "latex-text-renderer.h"
 #include <print.h>
 #include "extension/system.h"
 #include "extension/print.h"
 #include <print.h>
 #include "extension/system.h"
 #include "extension/print.h"
@@ -110,49 +111,6 @@ pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int
     return ret;
 }
 
     return ret;
 }
 
-static bool
-latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, 
-                                    const gchar * const exportId, bool exportDrawing, bool exportCanvas)
-{
-    sp_document_ensure_up_to_date(doc);
-
-/* Start */
-
-    SPItem *base = NULL;
-
-    bool pageBoundingBox = true;
-    if (exportId && strcmp(exportId, "")) {
-        // we want to export the given item only
-        base = SP_ITEM(doc->getObjectById(exportId));
-        pageBoundingBox = exportCanvas;
-    }
-    else {
-        // we want to export the entire document from root
-        base = SP_ITEM(sp_document_root(doc));
-        pageBoundingBox = !exportDrawing;
-    }
-
-    if (!base)
-        return false;
-
-    /* Create renderer */
-    PDFLaTeXRenderer *renderer = new PDFLaTeXRenderer();
-
-    bool ret = renderer->setTargetFile(filename);
-    if (ret) {
-        /* Render document */
-        bool ret = renderer->setupDocument(doc, pageBoundingBox, base);
-        if (ret) {
-            renderer->renderItem(base);
-        }
-    }
-
-    delete renderer;
-
-    return ret;
-}
-
-
 /**
     \brief  This function calls the output module with the filename
     \param  mod   unused
 /**
     \brief  This function calls the output module with the filename
     \param  mod   unused
@@ -287,7 +245,7 @@ CairoRendererPdfOutput::init (void)
                                "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
                        "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
                                "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
                        "</param>\n"
                        "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
-                       "<param name=\"textToLaTeX\" gui-text=\"" N_("Exclude text, create LaTeX file") "\" type=\"boolean\">false</param>\n"
+                       "<param name=\"textToLaTeX\" gui-text=\"" N_("PDF+LaTeX: Omit text in PDF, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n"
                        "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
                        "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
                        "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n"
diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp
new file mode 100644 (file)
index 0000000..83bb7c5
--- /dev/null
@@ -0,0 +1,648 @@
+#define EXTENSION_INTERNAL_PDF_LATEX_RENDERER_CPP
+
+/** \file
+ * Rendering LaTeX file (pdf+latex output)
+ *
+ * The idea stems from GNUPlot's epslatex terminal output :-)
+ */
+/*
+ * Authors:
+ *   Johan Engelen <goejendaagh@zonnet.nl>
+ *   Miklos Erdelyi <erdelyim@gmail.com>
+ *
+ * Copyright (C) 2006-2010 Authors
+ *
+ * Licensed under GNU GPL
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef PANGO_ENABLE_BACKEND
+#define PANGO_ENABLE_BACKEND
+#endif
+
+#ifndef PANGO_ENABLE_ENGINE
+#define PANGO_ENABLE_ENGINE
+#endif
+
+
+#include <signal.h>
+#include <errno.h>
+
+#include "libnr/nr-rect.h"
+#include "libnrtype/Layout-TNG.h"
+#include <2geom/transforms.h>
+#include <2geom/pathvector.h>
+
+#include <glib/gmem.h>
+
+#include <glibmm/i18n.h>
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+#include "display/nr-arena-group.h"
+#include "display/curve.h"
+#include "display/canvas-bpath.h"
+#include "sp-item.h"
+#include "sp-item-group.h"
+#include "style.h"
+#include "marker.h"
+#include "sp-linear-gradient.h"
+#include "sp-radial-gradient.h"
+#include "sp-root.h"
+#include "sp-use.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
+#include "sp-mask.h"
+#include "sp-clippath.h"
+#include "text-editing.h"
+
+#include <unit-constants.h>
+#include "helper/png-write.h"
+#include "helper/pixbuf-ops.h"
+
+#include "latex-text-renderer.h"
+#include "extension/system.h"
+
+#include "io/sys.h"
+
+#include <cairo.h>
+
+// include support for only the compiled-in surface types
+#ifdef CAIRO_HAS_PDF_SURFACE
+#include <cairo-pdf.h>
+#endif
+#ifdef CAIRO_HAS_PS_SURFACE
+#include <cairo-ps.h>
+#endif
+
+//#define TRACE(_args) g_message(_args)
+#define TRACE(_args)
+//#define TEST(_args) _args
+#define TEST(_args)
+
+// FIXME: expose these from sp-clippath/mask.cpp
+struct SPClipPathView {
+    SPClipPathView *next;
+    unsigned int key;
+    NRArenaItem *arenaitem;
+    NRRect bbox;
+};
+
+struct SPMaskView {
+    SPMaskView *next;
+    unsigned int key;
+    NRArenaItem *arenaitem;
+    NRRect bbox;
+};
+
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+bool
+latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, 
+                                    const gchar * const exportId, bool exportDrawing, bool exportCanvas)
+{
+    sp_document_ensure_up_to_date(doc);
+
+    SPItem *base = NULL;
+
+    bool pageBoundingBox = true;
+    if (exportId && strcmp(exportId, "")) {
+        // we want to export the given item only
+        base = SP_ITEM(doc->getObjectById(exportId));
+        pageBoundingBox = exportCanvas;
+    }
+    else {
+        // we want to export the entire document from root
+        base = SP_ITEM(sp_document_root(doc));
+        pageBoundingBox = !exportDrawing;
+    }
+
+    if (!base)
+        return false;
+
+    /* Create renderer */
+    LaTeXTextRenderer *renderer = new LaTeXTextRenderer();
+
+    bool ret = renderer->setTargetFile(filename);
+    if (ret) {
+        /* Render document */
+        bool ret = renderer->setupDocument(doc, pageBoundingBox, base);
+        if (ret) {
+            renderer->renderItem(base);
+        }
+    }
+
+    delete renderer;
+
+    return ret;
+}
+
+LaTeXTextRenderer::LaTeXTextRenderer(void)
+  : _stream(NULL),
+    _filename(NULL),
+    _width(0),
+    _height(0)
+{
+    push_transform(Geom::identity());
+}
+
+LaTeXTextRenderer::~LaTeXTextRenderer(void)
+{
+    if (_stream) {
+        writePostamble();
+
+        fclose(_stream);
+    }
+
+    /* restore default signal handling for SIGPIPE */
+#if !defined(_WIN32) && !defined(__WIN32__)
+    (void) signal(SIGPIPE, SIG_DFL);
+#endif
+
+    if (_filename) {
+        g_free(_filename);
+    }
+
+    return;
+}
+
+/** This should create the output LaTeX file, and assign it to _stream.
+ * @return Returns true when succesfull
+ */
+bool
+LaTeXTextRenderer::setTargetFile(gchar const *filename) {
+    if (filename != NULL) {
+        while (isspace(*filename)) filename += 1;
+        
+        _filename = g_path_get_basename(filename);
+
+        gchar *filename_ext = g_strdup_printf("%s.tex", filename);
+        Inkscape::IO::dump_fopen_call(filename_ext, "K");
+        FILE *osf = Inkscape::IO::fopen_utf8name(filename_ext, "w+");
+        if (!osf) {
+            fprintf(stderr, "inkscape: fopen(%s): %s\n",
+                    filename_ext, strerror(errno));
+            return false;
+        }
+        _stream = osf;
+        g_free(filename_ext);
+    }
+
+    if (_stream) {
+        /* fixme: this is kinda icky */
+#if !defined(_WIN32) && !defined(__WIN32__)
+        (void) signal(SIGPIPE, SIG_IGN);
+#endif
+    }
+
+    fprintf(_stream, "%%%% Creator: Inkscape %s, www.inkscape.org\n", PACKAGE_STRING);
+    fprintf(_stream, "%%%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010\n");
+    fprintf(_stream, "%%%% Accompanies image file '%s' (pdf, eps, ps)\n", _filename);
+    fprintf(_stream, "%%%%");
+    /* flush this to test output stream as early as possible */
+    if (fflush(_stream)) {
+        if (ferror(_stream)) {
+            g_print("Error %d on LaTeX file output stream: %s\n", errno,
+                    g_strerror(errno));
+        }
+        g_print("Output to LaTeX file failed\n");
+        /* fixme: should use pclose() for pipes */
+        fclose(_stream);
+        _stream = NULL;
+        fflush(stdout);
+        return false;
+    }
+
+    writePreamble();
+
+    return true;
+}
+
+static char const preamble[] =
+"%% To include the image in your LaTeX document, write\n"
+"%%   \\setlength{\\unitlength}{<desired width>}\n"
+"%%   \\input{<filename>.tex}\n"
+"%% instead of\n"
+"%%   \\includegraphics[width=<desired width>]{<filename>.pdf}\n"
+"\n"
+"\\begingroup                                                                              \n"
+"  \\makeatletter                                                                          \n"
+"  \\providecommand\\color[2][]{%                                                          \n"
+"    \\GenericError{(Inkscape) \\space\\space\\@spaces}{%                                  \n"
+"      Color is used for the text in Inkscape, but the color package color is not loaded.  \n"
+"    }{Either use black text in Inkscape or load the package                               \n"
+"      color.sty in LaTeX.}%                                                               \n"
+"    \\renewcommand\\color[2][]{}%                                                         \n"
+"  }%%                                                                                     \n"
+"  \\providecommand\\rotatebox[2]{#2}%                                                     \n"
+"  \\makeatother                                                                           \n";
+
+static char const postamble[] =
+"  \\end{picture}%                                                                          \n"
+"\\endgroup                                                                                 \n";
+
+void
+LaTeXTextRenderer::writePreamble()
+{
+    fprintf(_stream, "%s", preamble);
+}
+void
+LaTeXTextRenderer::writePostamble()
+{
+    fprintf(_stream, "%s", postamble);
+}
+
+void
+LaTeXTextRenderer::sp_group_render(SPItem *item)
+{
+    SPGroup *group = SP_GROUP(item);
+
+    GSList *l = g_slist_reverse(group->childList(false));
+    while (l) {
+        SPObject *o = SP_OBJECT (l->data);
+        if (SP_IS_ITEM(o)) {
+            renderItem (SP_ITEM (o));
+        }
+        l = g_slist_remove (l, o);
+    }
+}
+
+void
+LaTeXTextRenderer::sp_use_render(SPItem *item)
+{
+/*
+    bool translated = false;
+    SPUse *use = SP_USE(item);
+
+    if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
+        Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed));
+        ctx->pushState();
+        ctx->transform(&tp);
+        translated = true;
+    }
+
+    if (use->child && SP_IS_ITEM(use->child)) {
+        renderItem(SP_ITEM(use->child));
+    }
+
+    if (translated) {
+        ctx->popState();
+    }
+*/
+}
+
+void
+LaTeXTextRenderer::sp_text_render(SPItem *item)
+{
+    SPText *textobj = SP_TEXT (item);
+
+    Geom::Matrix i2doc = sp_item_i2doc_affine(item);
+    push_transform(i2doc);
+
+    gchar *str = sp_te_get_string_multiline(item);
+
+    // get position and alignment
+    Geom::Point pos;
+    gchar *alignment = NULL;
+    Geom::OptRect bbox = item->getBounds(transform());
+    Geom::Interval bbox_x = (*bbox)[Geom::X];
+    Geom::Interval bbox_y = (*bbox)[Geom::Y];
+    SPStyle *style = SP_OBJECT_STYLE (SP_OBJECT(item));
+    switch (style->text_anchor.computed) {
+    case SP_CSS_TEXT_ANCHOR_START:
+        pos = Geom::Point( bbox_x.min() , bbox_y.middle() );
+        alignment = "[l]";
+        break;
+    case SP_CSS_TEXT_ANCHOR_END:
+        pos = Geom::Point( bbox_x.max() , bbox_y.middle() );
+        alignment = "[r]";
+        break;
+    case SP_CSS_TEXT_ANCHOR_MIDDLE:
+    default:
+        pos = bbox->midpoint();
+        alignment = "";
+        break;
+    }
+
+    // get rotation
+    Geom::Matrix wotransl = i2doc.without_translation();
+    double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
+    bool has_rotation = !Geom::are_near(degrees,0.);
+
+    pop_transform();
+
+    // write to LaTeX
+    Inkscape::SVGOStringStream os;
+
+//    os << "\\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){\\makebox(0,0)[" << alignment << "]{\\strut{}" << str << "}}%%\n";
+    os << "    \\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){";
+    os << "\\makebox(0,0)" << alignment << "{";
+    if (has_rotation) {
+        os << "\\rotatebox{" << degrees << "}{";
+    }
+    os <<   str;
+    if (has_rotation) {
+        os << "}"; // rotatebox end
+    }
+    os << "}"; //makebox end
+    os << "}%\n"; // put end
+
+    fprintf(_stream, "%s", os.str().c_str());
+}
+
+void
+LaTeXTextRenderer::sp_flowtext_render(SPItem *item)
+{
+/*    SPFlowtext *group = SP_FLOWTEXT(item);
+
+    // write to LaTeX
+    Inkscape::SVGOStringStream os;
+
+    os << "  \\begin{picture}(" << _width << "," << _height << ")%%\n";
+    os << "    \\gplgaddtomacro\\gplbacktext{%%\n";
+    os << "      \\csname LTb\\endcsname%%\n";
+    os << "\\put(0,0){\\makebox(0,0)[lb]{\\strut{}Position}}%%\n";
+
+    fprintf(_stream, "%s", os.str().c_str());
+*/
+}
+
+void
+LaTeXTextRenderer::sp_root_render(SPItem *item)
+{
+    SPRoot *root = SP_ROOT(item);
+
+//    ctx->pushState();
+//    setStateForItem(ctx, item);
+    Geom::Matrix tempmat (root->c2p);
+    push_transform(tempmat);
+    sp_group_render(item);
+    pop_transform();
+}
+
+void
+LaTeXTextRenderer::sp_item_invoke_render(SPItem *item)
+{
+    // Check item's visibility
+    if (item->isHidden()) {
+        return;
+    }
+
+    if (SP_IS_ROOT(item)) {
+        TRACE(("root\n"));
+        return sp_root_render(item);
+    } else if (SP_IS_GROUP(item)) {
+        TRACE(("group\n"));
+        return sp_group_render(item);
+    } else if (SP_IS_USE(item)) {
+        TRACE(("use begin---\n"));
+        sp_use_render(item);
+        TRACE(("---use end\n"));
+    } else if (SP_IS_TEXT(item)) {
+        TRACE(("text\n"));
+        return sp_text_render(item);
+    } else if (SP_IS_FLOWTEXT(item)) {
+        TRACE(("flowtext\n"));
+        return sp_flowtext_render(item);
+    }
+    // We are not interested in writing the other SPItem types to LaTeX
+}
+
+void
+LaTeXTextRenderer::setStateForItem(SPItem const *item)
+{
+/*
+    SPStyle const *style = SP_OBJECT_STYLE(item);
+    ctx->setStateForStyle(style);
+
+    CairoRenderState *state = ctx->getCurrentState();
+    state->clip_path = item->clip_ref->getObject();
+    state->mask = item->mask_ref->getObject();
+    state->item_transform = Geom::Matrix (item->transform);
+
+    // If parent_has_userspace is true the parent state's transform
+    // has to be used for the mask's/clippath's context.
+    // This is so because we use the image's/(flow)text's transform for positioning
+    // instead of explicitly specifying it and letting the renderer do the
+    // transformation before rendering the item.
+    if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_IMAGE(item))
+        state->parent_has_userspace = TRUE;
+    TRACE(("setStateForItem opacity: %f\n", state->opacity));
+*/
+}
+
+void
+LaTeXTextRenderer::renderItem(SPItem *item)
+{
+//    ctx->pushState();
+//    setStateForItem(ctx, item);
+
+//    CairoRenderState *state = ctx->getCurrentState();
+//    state->need_layer = ( state->mask || state->clip_path || state->opacity != 1.0 );
+
+    // Draw item on a temporary surface so a mask, clip path, or opacity can be applied to it.
+//    if (state->need_layer) {
+//        state->merge_opacity = FALSE;
+//        ctx->pushLayer();
+//    }
+    Geom::Matrix tempmat (item->transform);
+//    ctx->transform(&tempmat);
+    sp_item_invoke_render(item);
+
+//    if (state->need_layer)
+//        ctx->popLayer();
+
+//    ctx->popState();
+}
+
+bool
+LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base)
+{
+// The boundingbox calculation here should be exactly the same as the one by CairoRenderer::setupDocument !
+
+    if (!base)
+        base = SP_ITEM(sp_document_root(doc));
+
+    NRRect d;
+    if (pageBoundingBox) {
+        d.x0 = d.y0 = 0;
+        d.x1 = ceil(sp_document_width(doc));
+        d.y1 = ceil(sp_document_height(doc));
+    } else {
+        sp_item_invoke_bbox(base, &d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX);
+    }
+
+    // scale all coordinates, such that the width of the image is 1, this is convenient for scaling the image in LaTeX
+    double scale = 1/(d.x1-d.x0);
+    _width = (d.x1-d.x0) * scale;
+    _height = (d.y1-d.y0) * scale;
+    push_transform( Geom::Scale(scale, scale) );
+
+    if (!pageBoundingBox)
+    {
+        double high = sp_document_height(doc);
+
+        push_transform( Geom::Translate( -d.x0,
+                                         -d.y0 ) );
+    }
+
+    // flip y-axis
+    push_transform( Geom::Scale(1,-1) * Geom::Translate(0, sp_document_height(doc)) );
+
+    // write the info to LaTeX
+    Inkscape::SVGOStringStream os;
+
+    os << "  \\begin{picture}(" << _width << "," << _height << ")%\n";
+    // strip pathname, as it is probably desired. Having a specific path in the TeX file is not convenient.
+    os << "    \\put(0,0){\\includegraphics[width=\\unitlength]{" << _filename << "}}%\n";
+
+    fprintf(_stream, "%s", os.str().c_str());
+
+    return true;
+}
+
+Geom::Matrix const &
+LaTeXTextRenderer::transform()
+{
+    return _transform_stack.top();
+}
+
+void
+LaTeXTextRenderer::push_transform(Geom::Matrix const &tr)
+{
+    if(_transform_stack.size()){
+        Geom::Matrix tr_top = _transform_stack.top();
+        _transform_stack.push(tr * tr_top);
+    } else {
+        _transform_stack.push(tr);
+    }
+}
+
+void
+LaTeXTextRenderer::pop_transform()
+{
+    _transform_stack.pop();
+}
+
+/*
+#include "macros.h" // SP_PRINT_*
+
+// Apply an SVG clip path
+void
+LaTeXTextRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
+{
+    g_assert( ctx != NULL && ctx->_is_valid );
+
+    if (cp == NULL)
+        return;
+
+    CairoRenderContext::CairoRenderMode saved_mode = ctx->getRenderMode();
+    ctx->setRenderMode(CairoRenderContext::RENDER_MODE_CLIP);
+
+    Geom::Matrix saved_ctm;
+    if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
+        //SP_PRINT_DRECT("clipd", cp->display->bbox);
+        NRRect clip_bbox(cp->display->bbox);
+        Geom::Matrix t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0));
+        t[4] = clip_bbox.x0;
+        t[5] = clip_bbox.y0;
+        t *= ctx->getCurrentState()->transform;
+        ctx->getTransform(&saved_ctm);
+        ctx->setTransform(&t);
+    }
+
+    TRACE(("BEGIN clip\n"));
+    SPObject *co = SP_OBJECT(cp);
+    for (SPObject *child = sp_object_first_child(co) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
+        if (SP_IS_ITEM(child)) {
+            SPItem *item = SP_ITEM(child);
+
+            // combine transform of the item in clippath and the item using clippath:
+            Geom::Matrix tempmat (item->transform);
+            tempmat = tempmat * (ctx->getCurrentState()->item_transform);
+
+            // render this item in clippath
+            ctx->pushState();
+            ctx->transform(&tempmat);
+            setStateForItem(ctx, item);
+            sp_item_invoke_render(item, ctx);
+            ctx->popState();
+        }
+    }
+    TRACE(("END clip\n"));
+
+    // do clipping only if this was the first call to applyClipPath
+    if (ctx->getClipMode() == CairoRenderContext::CLIP_MODE_PATH
+        && saved_mode == CairoRenderContext::RENDER_MODE_NORMAL)
+        cairo_clip(ctx->_cr);
+
+    if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX)
+        ctx->setTransform(&saved_ctm);
+
+    ctx->setRenderMode(saved_mode);
+}
+
+// Apply an SVG mask
+void
+LaTeXTextRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask)
+{
+    g_assert( ctx != NULL && ctx->_is_valid );
+
+    if (mask == NULL)
+        return;
+
+    //SP_PRINT_DRECT("maskd", &mask->display->bbox);
+    NRRect mask_bbox(mask->display->bbox);
+    // TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ?
+    if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
+        Geom::Matrix t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0));
+        t[4] = mask_bbox.x0;
+        t[5] = mask_bbox.y0;
+        t *= ctx->getCurrentState()->transform;
+        ctx->setTransform(&t);
+    }
+
+    // Clip mask contents... but...
+    // The mask's bounding box is the "geometric bounding box" which doesn't allow for
+    // filters which extend outside the bounding box. So don't clip.
+    // ctx->addClippingRect(mask_bbox.x0, mask_bbox.y0, mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0);
+
+    ctx->pushState();
+
+    TRACE(("BEGIN mask\n"));
+    SPObject *co = SP_OBJECT(mask);
+    for (SPObject *child = sp_object_first_child(co) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
+        if (SP_IS_ITEM(child)) {
+            SPItem *item = SP_ITEM(child);
+            renderItem(ctx, item);
+        }
+    }
+    TRACE(("END mask\n"));
+
+    ctx->popState();
+}
+*/
+
+}  /* namespace Internal */
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#undef TRACE
+
+/* End of GNU GPL code */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h
new file mode 100644 (file)
index 0000000..a3c4190
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef EXTENSION_INTERNAL_PDF_LATEX_RENDERER_H_SEEN
+#define EXTENSION_INTERNAL_PDF_LATEX_RENDERER_H_SEEN
+
+/** \file
+ * Declaration of LaTeXTextRenderer, used for rendering the accompanying LaTeX file when saving PDF output + LaTeX 
+ */
+/*
+ * Authors:
+ *  Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * Copyright (C) 2010 Authors
+ * 
+ * Licensed under GNU GPL
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "extension/extension.h"
+#include <set>
+#include <string>
+
+#include "style.h"
+
+#include <cairo.h>
+
+#include <2geom/matrix.h>
+#include <stack>
+
+class SPClipPath;
+class SPMask;
+class SPItem;
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+bool latex_render_document_text_to_file(SPDocument *doc, gchar const *filename, const gchar * const exportId, bool exportDrawing, bool exportCanvas);
+
+class LaTeXTextRenderer {
+public:
+    LaTeXTextRenderer();
+    virtual ~LaTeXTextRenderer();
+
+    bool setTargetFile(gchar const *filename);
+
+    void setStateForItem(SPItem const *item);
+
+//    void applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp);
+//    void applyMask(CairoRenderContext *ctx, SPMask const *mask);
+
+    /** Initializes the LaTeXTextRenderer according to the specified
+    SPDocument. Important to set the boundingbox to the pdf boundingbox */
+    bool setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base);
+
+    /** Traverses the object tree and invokes the render methods. */
+    void renderItem(SPItem *item);
+
+protected:
+    FILE * _stream;
+    gchar * _filename;
+
+    void push_transform(Geom::Matrix const &transform);
+    Geom::Matrix const & transform();
+    void pop_transform();
+    std::stack<Geom::Matrix> _transform_stack;
+    double _width;
+    double _height;
+
+    void writePreamble();
+    void writePostamble();
+
+    void sp_item_invoke_render(SPItem *item);
+    void sp_root_render(SPItem *item);
+    void sp_group_render(SPItem *item);
+    void sp_use_render(SPItem *item);
+    void sp_text_render(SPItem *item);
+    void sp_flowtext_render(SPItem *item);
+};
+
+}  /* namespace Internal */
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+#endif /* !EXTENSION_INTERNAL_CAIRO_RENDERER_H_SEEN */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/extension/internal/pdflatex-renderer.cpp b/src/extension/internal/pdflatex-renderer.cpp
deleted file mode 100644 (file)
index b70bac1..0000000
+++ /dev/null
@@ -1,609 +0,0 @@
-#define EXTENSION_INTERNAL_PDF_LATEX_RENDERER_CPP
-
-/** \file
- * Rendering LaTeX file (pdf+latex output)
- *
- * The idea stems from GNUPlot's epslatex terminal output :-)
- */
-/*
- * Authors:
- *   Johan Engelen <goejendaagh@zonnet.nl>
- *   Miklos Erdelyi <erdelyim@gmail.com>
- *
- * Copyright (C) 2006-2010 Authors
- *
- * Licensed under GNU GPL
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#ifndef PANGO_ENABLE_BACKEND
-#define PANGO_ENABLE_BACKEND
-#endif
-
-#ifndef PANGO_ENABLE_ENGINE
-#define PANGO_ENABLE_ENGINE
-#endif
-
-
-#include <signal.h>
-#include <errno.h>
-
-#include "libnr/nr-rect.h"
-#include "libnrtype/Layout-TNG.h"
-#include <2geom/transforms.h>
-#include <2geom/pathvector.h>
-
-#include <glib/gmem.h>
-
-#include <glibmm/i18n.h>
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-arena-group.h"
-#include "display/curve.h"
-#include "display/canvas-bpath.h"
-#include "sp-item.h"
-#include "sp-item-group.h"
-#include "style.h"
-#include "marker.h"
-#include "sp-linear-gradient.h"
-#include "sp-radial-gradient.h"
-#include "sp-root.h"
-#include "sp-use.h"
-#include "sp-text.h"
-#include "sp-flowtext.h"
-#include "sp-mask.h"
-#include "sp-clippath.h"
-#include "text-editing.h"
-
-#include <unit-constants.h>
-#include "helper/png-write.h"
-#include "helper/pixbuf-ops.h"
-
-#include "pdflatex-renderer.h"
-#include "extension/system.h"
-
-#include "io/sys.h"
-
-#include <cairo.h>
-
-// include support for only the compiled-in surface types
-#ifdef CAIRO_HAS_PDF_SURFACE
-#include <cairo-pdf.h>
-#endif
-#ifdef CAIRO_HAS_PS_SURFACE
-#include <cairo-ps.h>
-#endif
-
-//#define TRACE(_args) g_message(_args)
-#define TRACE(_args)
-//#define TEST(_args) _args
-#define TEST(_args)
-
-// FIXME: expose these from sp-clippath/mask.cpp
-struct SPClipPathView {
-    SPClipPathView *next;
-    unsigned int key;
-    NRArenaItem *arenaitem;
-    NRRect bbox;
-};
-
-struct SPMaskView {
-    SPMaskView *next;
-    unsigned int key;
-    NRArenaItem *arenaitem;
-    NRRect bbox;
-};
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-
-PDFLaTeXRenderer::PDFLaTeXRenderer(void)
-  : _stream(NULL),
-    _filename(NULL),
-    _width(0),
-    _height(0)
-{
-    push_transform(Geom::identity());
-}
-
-PDFLaTeXRenderer::~PDFLaTeXRenderer(void)
-{
-    if (_stream) {
-        writePostamble();
-
-        fclose(_stream);
-    }
-
-    /* restore default signal handling for SIGPIPE */
-#if !defined(_WIN32) && !defined(__WIN32__)
-    (void) signal(SIGPIPE, SIG_DFL);
-#endif
-
-    if (_filename) {
-        g_free(_filename);
-    }
-
-    return;
-}
-
-/** This should create the output LaTeX file, and assign it to _stream.
- * @return Returns true when succesfull
- */
-bool
-PDFLaTeXRenderer::setTargetFile(gchar const *filename) {
-    if (filename != NULL) {
-        while (isspace(*filename)) filename += 1;
-        
-        _filename = g_strdup(filename);
-
-        gchar *filename_ext = g_strdup_printf("%s.tex", filename);
-        Inkscape::IO::dump_fopen_call(filename_ext, "K");
-        FILE *osf = Inkscape::IO::fopen_utf8name(filename_ext, "w+");
-        if (!osf) {
-            fprintf(stderr, "inkscape: fopen(%s): %s\n",
-                    filename_ext, strerror(errno));
-            return false;
-        }
-        _stream = osf;
-        g_free(filename_ext);
-    }
-
-    if (_stream) {
-        /* fixme: this is kinda icky */
-#if !defined(_WIN32) && !defined(__WIN32__)
-        (void) signal(SIGPIPE, SIG_IGN);
-#endif
-    }
-
-    fprintf(_stream, "%%%% Creator: Inkscape %s, www.inkscape.org\n", PACKAGE_STRING);
-    fprintf(_stream, "%%%% PDF + LaTeX output extension by Johan Engelen, 2010\n");
-    fprintf(_stream, "%%%% Accompanies %s.pdf\n", _filename);
-    /* flush this to test output stream as early as possible */
-    if (fflush(_stream)) {
-        if (ferror(_stream)) {
-            g_print("Error %d on LaTeX file output stream: %s\n", errno,
-                    g_strerror(errno));
-        }
-        g_print("Output to LaTeX file failed\n");
-        /* fixme: should use pclose() for pipes */
-        fclose(_stream);
-        _stream = NULL;
-        fflush(stdout);
-        return false;
-    }
-
-    writePreamble();
-
-    return true;
-}
-
-static char const preamble[] =
-"%% To include the image in your LaTeX document, write\n"
-"%%   \\setlength{\\unitlength}{<desired width>}\n"
-"%%   \\input{<filename>.tex}\n"
-"%% instead of\n"
-"%%   \\includegraphics[width=<desired width>]{<filename>.pdf}\n"
-"\n"
-"\\begingroup                                                                              \n"
-"  \\makeatletter                                                                          \n"
-"  \\providecommand\\color[2][]{%                                                          \n"
-"    \\GenericError{(Inkscape) \\space\\space\\@spaces}{%                                  \n"
-"      Color is used for the text in Inkscape, but the color package color is not loaded.  \n"
-"    }{Either use black text in Inkscape or load the package                               \n"
-"      color.sty in LaTeX.}%                                                               \n"
-"    \\renewcommand\\color[2][]{}%                                                         \n"
-"  }%%                                                                                     \n"
-"  \\providecommand\\rotatebox[2]{#2}%                                                     \n"
-"  \\makeatother                                                                           \n";
-
-static char const postamble[] =
-"  \\end{picture}%                                                                          \n"
-"\\endgroup                                                                                 \n";
-
-void
-PDFLaTeXRenderer::writePreamble()
-{
-    fprintf(_stream, "%s", preamble);
-}
-void
-PDFLaTeXRenderer::writePostamble()
-{
-    fprintf(_stream, "%s", postamble);
-}
-
-void
-PDFLaTeXRenderer::sp_group_render(SPItem *item)
-{
-    SPGroup *group = SP_GROUP(item);
-
-    GSList *l = g_slist_reverse(group->childList(false));
-    while (l) {
-        SPObject *o = SP_OBJECT (l->data);
-        if (SP_IS_ITEM(o)) {
-            renderItem (SP_ITEM (o));
-        }
-        l = g_slist_remove (l, o);
-    }
-}
-
-void
-PDFLaTeXRenderer::sp_use_render(SPItem *item)
-{
-/*
-    bool translated = false;
-    SPUse *use = SP_USE(item);
-
-    if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
-        Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed));
-        ctx->pushState();
-        ctx->transform(&tp);
-        translated = true;
-    }
-
-    if (use->child && SP_IS_ITEM(use->child)) {
-        renderItem(SP_ITEM(use->child));
-    }
-
-    if (translated) {
-        ctx->popState();
-    }
-*/
-}
-
-void
-PDFLaTeXRenderer::sp_text_render(SPItem *item)
-{
-    SPText *textobj = SP_TEXT (item);
-
-    Geom::Matrix i2doc = sp_item_i2doc_affine(item);
-    push_transform(i2doc);
-
-    gchar *str = sp_te_get_string_multiline(item);
-
-    // get position and alignment
-    Geom::Point pos;
-    gchar *alignment = NULL;
-    Geom::OptRect bbox = item->getBounds(transform());
-    Geom::Interval bbox_x = (*bbox)[Geom::X];
-    Geom::Interval bbox_y = (*bbox)[Geom::Y];
-    SPStyle *style = SP_OBJECT_STYLE (SP_OBJECT(item));
-    switch (style->text_anchor.computed) {
-    case SP_CSS_TEXT_ANCHOR_START:
-        pos = Geom::Point( bbox_x.min() , bbox_y.middle() );
-        alignment = "[l]";
-        break;
-    case SP_CSS_TEXT_ANCHOR_END:
-        pos = Geom::Point( bbox_x.max() , bbox_y.middle() );
-        alignment = "[r]";
-        break;
-    case SP_CSS_TEXT_ANCHOR_MIDDLE:
-    default:
-        pos = bbox->midpoint();
-        alignment = "";
-        break;
-    }
-
-    // get rotation
-    Geom::Matrix wotransl = i2doc.without_translation();
-    double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
-    bool has_rotation = !Geom::are_near(degrees,0.);
-
-    pop_transform();
-
-    // write to LaTeX
-    Inkscape::SVGOStringStream os;
-
-//    os << "\\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){\\makebox(0,0)[" << alignment << "]{\\strut{}" << str << "}}%%\n";
-    os << "    \\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){";
-    os << "\\makebox(0,0)" << alignment << "{";
-    if (has_rotation) {
-        os << "\\rotatebox{" << degrees << "}{";
-    }
-    os <<   str;
-    if (has_rotation) {
-        os << "}"; // rotatebox end
-    }
-    os << "}"; //makebox end
-    os << "}%\n"; // put end
-
-    fprintf(_stream, "%s", os.str().c_str());
-}
-
-void
-PDFLaTeXRenderer::sp_flowtext_render(SPItem *item)
-{
-/*    SPFlowtext *group = SP_FLOWTEXT(item);
-
-    // write to LaTeX
-    Inkscape::SVGOStringStream os;
-
-    os << "  \\begin{picture}(" << _width << "," << _height << ")%%\n";
-    os << "    \\gplgaddtomacro\\gplbacktext{%%\n";
-    os << "      \\csname LTb\\endcsname%%\n";
-    os << "\\put(0,0){\\makebox(0,0)[lb]{\\strut{}Position}}%%\n";
-
-    fprintf(_stream, "%s", os.str().c_str());
-*/
-}
-
-void
-PDFLaTeXRenderer::sp_root_render(SPItem *item)
-{
-    SPRoot *root = SP_ROOT(item);
-
-//    ctx->pushState();
-//    setStateForItem(ctx, item);
-    Geom::Matrix tempmat (root->c2p);
-    push_transform(tempmat);
-    sp_group_render(item);
-    pop_transform();
-}
-
-void
-PDFLaTeXRenderer::sp_item_invoke_render(SPItem *item)
-{
-    // Check item's visibility
-    if (item->isHidden()) {
-        return;
-    }
-
-    if (SP_IS_ROOT(item)) {
-        TRACE(("root\n"));
-        return sp_root_render(item);
-    } else if (SP_IS_GROUP(item)) {
-        TRACE(("group\n"));
-        return sp_group_render(item);
-    } else if (SP_IS_USE(item)) {
-        TRACE(("use begin---\n"));
-        sp_use_render(item);
-        TRACE(("---use end\n"));
-    } else if (SP_IS_TEXT(item)) {
-        TRACE(("text\n"));
-        return sp_text_render(item);
-    } else if (SP_IS_FLOWTEXT(item)) {
-        TRACE(("flowtext\n"));
-        return sp_flowtext_render(item);
-    }
-    // We are not interested in writing the other SPItem types to LaTeX
-}
-
-void
-PDFLaTeXRenderer::setStateForItem(SPItem const *item)
-{
-/*
-    SPStyle const *style = SP_OBJECT_STYLE(item);
-    ctx->setStateForStyle(style);
-
-    CairoRenderState *state = ctx->getCurrentState();
-    state->clip_path = item->clip_ref->getObject();
-    state->mask = item->mask_ref->getObject();
-    state->item_transform = Geom::Matrix (item->transform);
-
-    // If parent_has_userspace is true the parent state's transform
-    // has to be used for the mask's/clippath's context.
-    // This is so because we use the image's/(flow)text's transform for positioning
-    // instead of explicitly specifying it and letting the renderer do the
-    // transformation before rendering the item.
-    if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_IMAGE(item))
-        state->parent_has_userspace = TRUE;
-    TRACE(("setStateForItem opacity: %f\n", state->opacity));
-*/
-}
-
-void
-PDFLaTeXRenderer::renderItem(SPItem *item)
-{
-//    ctx->pushState();
-//    setStateForItem(ctx, item);
-
-//    CairoRenderState *state = ctx->getCurrentState();
-//    state->need_layer = ( state->mask || state->clip_path || state->opacity != 1.0 );
-
-    // Draw item on a temporary surface so a mask, clip path, or opacity can be applied to it.
-//    if (state->need_layer) {
-//        state->merge_opacity = FALSE;
-//        ctx->pushLayer();
-//    }
-    Geom::Matrix tempmat (item->transform);
-//    ctx->transform(&tempmat);
-    sp_item_invoke_render(item);
-
-//    if (state->need_layer)
-//        ctx->popLayer();
-
-//    ctx->popState();
-}
-
-bool
-PDFLaTeXRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base)
-{
-// The boundingbox calculation here should be exactly the same as the one by CairoRenderer::setupDocument !
-
-    if (!base)
-        base = SP_ITEM(sp_document_root(doc));
-
-    NRRect d;
-    if (pageBoundingBox) {
-        d.x0 = d.y0 = 0;
-        d.x1 = ceil(sp_document_width(doc));
-        d.y1 = ceil(sp_document_height(doc));
-    } else {
-        sp_item_invoke_bbox(base, &d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX);
-    }
-
-    // scale all coordinates, such that the width of the image is 1, this is convenient for scaling the image in LaTeX
-    double scale = 1/(d.x1-d.x0);
-    _width = (d.x1-d.x0) * scale;
-    _height = (d.y1-d.y0) * scale;
-    push_transform( Geom::Scale(scale, scale) );
-
-    if (!pageBoundingBox)
-    {
-        double high = sp_document_height(doc);
-
-        push_transform( Geom::Translate( -d.x0,
-                                         -d.y0 ) );
-    }
-
-    // flip y-axis
-    push_transform( Geom::Scale(1,-1) * Geom::Translate(0, sp_document_height(doc)) );
-
-    // write the info to LaTeX
-    Inkscape::SVGOStringStream os;
-
-    os << "  \\begin{picture}(" << _width << "," << _height << ")%\n";
-    // strip pathname, as it is probably desired. Having a specific path in the TeX file is not convenient.
-    gchar *figurefile = g_path_get_basename(_filename);
-    os << "    \\put(0,0){\\includegraphics[width=\\unitlength]{" << figurefile << ".pdf}}%\n";
-    g_free(figurefile);
-
-    fprintf(_stream, "%s", os.str().c_str());
-
-    return true;
-}
-
-Geom::Matrix const &
-PDFLaTeXRenderer::transform()
-{
-    return _transform_stack.top();
-}
-
-void
-PDFLaTeXRenderer::push_transform(Geom::Matrix const &tr)
-{
-    if(_transform_stack.size()){
-        Geom::Matrix tr_top = _transform_stack.top();
-        _transform_stack.push(tr * tr_top);
-    } else {
-        _transform_stack.push(tr);
-    }
-}
-
-void
-PDFLaTeXRenderer::pop_transform()
-{
-    _transform_stack.pop();
-}
-
-/*
-#include "macros.h" // SP_PRINT_*
-
-// Apply an SVG clip path
-void
-PDFLaTeXRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
-{
-    g_assert( ctx != NULL && ctx->_is_valid );
-
-    if (cp == NULL)
-        return;
-
-    CairoRenderContext::CairoRenderMode saved_mode = ctx->getRenderMode();
-    ctx->setRenderMode(CairoRenderContext::RENDER_MODE_CLIP);
-
-    Geom::Matrix saved_ctm;
-    if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
-        //SP_PRINT_DRECT("clipd", cp->display->bbox);
-        NRRect clip_bbox(cp->display->bbox);
-        Geom::Matrix t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0));
-        t[4] = clip_bbox.x0;
-        t[5] = clip_bbox.y0;
-        t *= ctx->getCurrentState()->transform;
-        ctx->getTransform(&saved_ctm);
-        ctx->setTransform(&t);
-    }
-
-    TRACE(("BEGIN clip\n"));
-    SPObject *co = SP_OBJECT(cp);
-    for (SPObject *child = sp_object_first_child(co) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
-        if (SP_IS_ITEM(child)) {
-            SPItem *item = SP_ITEM(child);
-
-            // combine transform of the item in clippath and the item using clippath:
-            Geom::Matrix tempmat (item->transform);
-            tempmat = tempmat * (ctx->getCurrentState()->item_transform);
-
-            // render this item in clippath
-            ctx->pushState();
-            ctx->transform(&tempmat);
-            setStateForItem(ctx, item);
-            sp_item_invoke_render(item, ctx);
-            ctx->popState();
-        }
-    }
-    TRACE(("END clip\n"));
-
-    // do clipping only if this was the first call to applyClipPath
-    if (ctx->getClipMode() == CairoRenderContext::CLIP_MODE_PATH
-        && saved_mode == CairoRenderContext::RENDER_MODE_NORMAL)
-        cairo_clip(ctx->_cr);
-
-    if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX)
-        ctx->setTransform(&saved_ctm);
-
-    ctx->setRenderMode(saved_mode);
-}
-
-// Apply an SVG mask
-void
-PDFLaTeXRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask)
-{
-    g_assert( ctx != NULL && ctx->_is_valid );
-
-    if (mask == NULL)
-        return;
-
-    //SP_PRINT_DRECT("maskd", &mask->display->bbox);
-    NRRect mask_bbox(mask->display->bbox);
-    // TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ?
-    if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
-        Geom::Matrix t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0));
-        t[4] = mask_bbox.x0;
-        t[5] = mask_bbox.y0;
-        t *= ctx->getCurrentState()->transform;
-        ctx->setTransform(&t);
-    }
-
-    // Clip mask contents... but...
-    // The mask's bounding box is the "geometric bounding box" which doesn't allow for
-    // filters which extend outside the bounding box. So don't clip.
-    // ctx->addClippingRect(mask_bbox.x0, mask_bbox.y0, mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0);
-
-    ctx->pushState();
-
-    TRACE(("BEGIN mask\n"));
-    SPObject *co = SP_OBJECT(mask);
-    for (SPObject *child = sp_object_first_child(co) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
-        if (SP_IS_ITEM(child)) {
-            SPItem *item = SP_ITEM(child);
-            renderItem(ctx, item);
-        }
-    }
-    TRACE(("END mask\n"));
-
-    ctx->popState();
-}
-*/
-
-}  /* namespace Internal */
-}  /* namespace Extension */
-}  /* namespace Inkscape */
-
-#undef TRACE
-
-/* End of GNU GPL code */
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/extension/internal/pdflatex-renderer.h b/src/extension/internal/pdflatex-renderer.h
deleted file mode 100644 (file)
index 93c06b1..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef EXTENSION_INTERNAL_PDF_LATEX_RENDERER_H_SEEN
-#define EXTENSION_INTERNAL_PDF_LATEX_RENDERER_H_SEEN
-
-/** \file
- * Declaration of PDFLaTeXRenderer, used for rendering the accompanying LaTeX file when saving PDF output + LaTeX 
- */
-/*
- * Authors:
- *  Johan Engelen <goejendaagh@zonnet.nl>
- *
- * Copyright (C) 2010 Authors
- * 
- * Licensed under GNU GPL
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "extension/extension.h"
-#include <set>
-#include <string>
-
-#include "style.h"
-
-#include <cairo.h>
-
-#include <2geom/matrix.h>
-#include <stack>
-
-class SPClipPath;
-class SPMask;
-class SPItem;
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-class PDFLaTeXRenderer {
-public:
-    PDFLaTeXRenderer();
-    virtual ~PDFLaTeXRenderer();
-
-    bool setTargetFile(gchar const *filename);
-
-    void setStateForItem(SPItem const *item);
-
-//    void applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp);
-//    void applyMask(CairoRenderContext *ctx, SPMask const *mask);
-
-    /** Initializes the PDFLaTeXRenderer according to the specified
-    SPDocument. Important to set the boundingbox to the pdf boundingbox */
-    bool setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base);
-
-    /** Traverses the object tree and invokes the render methods. */
-    void renderItem(SPItem *item);
-
-protected:
-    FILE * _stream;
-    gchar * _filename;
-
-    void push_transform(Geom::Matrix const &transform);
-    Geom::Matrix const & transform();
-    void pop_transform();
-    std::stack<Geom::Matrix> _transform_stack;
-    double _width;
-    double _height;
-
-    void writePreamble();
-    void writePostamble();
-
-    void sp_item_invoke_render(SPItem *item);
-    void sp_root_render(SPItem *item);
-    void sp_group_render(SPItem *item);
-    void sp_use_render(SPItem *item);
-    void sp_text_render(SPItem *item);
-    void sp_flowtext_render(SPItem *item);
-};
-
-}  /* namespace Internal */
-}  /* namespace Extension */
-}  /* namespace Inkscape */
-
-#endif /* !EXTENSION_INTERNAL_CAIRO_RENDERER_H_SEEN */
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 6b87df1941bcdae4ee48bf2bbd8138a0d583c22d..4bb5dfdc12e4aa2449bb872c18c6260d8c36e894 100644 (file)
@@ -143,7 +143,7 @@ enum {
     SP_ARG_EXPORT_PS,
     SP_ARG_EXPORT_EPS,
     SP_ARG_EXPORT_PDF,
     SP_ARG_EXPORT_PS,
     SP_ARG_EXPORT_EPS,
     SP_ARG_EXPORT_PDF,
-    SP_ARG_EXPORT_PDF_LATEX,
+    SP_ARG_EXPORT_LATEX,
 #ifdef WIN32
     SP_ARG_EXPORT_EMF,
 #endif //WIN32
 #ifdef WIN32
     SP_ARG_EXPORT_EMF,
 #endif //WIN32
@@ -182,7 +182,7 @@ static gchar *sp_export_dpi = NULL;
 static gchar *sp_export_area = NULL;
 static gboolean sp_export_area_drawing = FALSE;
 static gboolean sp_export_area_page = FALSE;
 static gchar *sp_export_area = NULL;
 static gboolean sp_export_area_drawing = FALSE;
 static gboolean sp_export_area_page = FALSE;
-static gboolean sp_export_pdf_latex = FALSE;
+static gboolean sp_export_latex = FALSE;
 static gchar *sp_export_width = NULL;
 static gchar *sp_export_height = NULL;
 static gchar *sp_export_id = NULL;
 static gchar *sp_export_width = NULL;
 static gchar *sp_export_height = NULL;
 static gchar *sp_export_id = NULL;
@@ -226,7 +226,7 @@ static void resetCommandlineGlobals() {
         sp_export_area = NULL;
         sp_export_area_drawing = FALSE;
         sp_export_area_page = FALSE;
         sp_export_area = NULL;
         sp_export_area_drawing = FALSE;
         sp_export_area_page = FALSE;
-        sp_export_pdf_latex = FALSE;
+        sp_export_latex = FALSE;
         sp_export_width = NULL;
         sp_export_height = NULL;
         sp_export_id = NULL;
         sp_export_width = NULL;
         sp_export_height = NULL;
         sp_export_id = NULL;
@@ -375,9 +375,9 @@ struct poptOption options[] = {
      N_("Export document to a PDF file"),
      N_("FILENAME")},
 
      N_("Export document to a PDF file"),
      N_("FILENAME")},
 
-    {"export-pdf-latex", 0,
-     POPT_ARG_NONE, &sp_export_pdf_latex, SP_ARG_EXPORT_PDF_LATEX,
-     N_("Export PDF without text. Besides the PDF, a LaTeX file is exported, putting the text on top of the PDF file. Include the result in LaTeX like: \\input{latexfile.tex}"),
+    {"export-latex", 0,
+     POPT_ARG_NONE, &sp_export_latex, SP_ARG_EXPORT_LATEX,
+     N_("Export PDF/PS/EPS without text. Besides the PDF/PS/EPS, a LaTeX file is exported, putting the text on top of the PDF/PS/EPS file. Include the result in LaTeX like: \\input{latexfile.tex}"),
      NULL},
 
 #ifdef WIN32
      NULL},
 
 #ifdef WIN32
@@ -654,7 +654,7 @@ main(int argc, char **argv)
             || !strncmp(argv[i], "--export-eps", 12)
             || !strcmp(argv[i], "-A")
             || !strncmp(argv[i], "--export-pdf", 12)
             || !strncmp(argv[i], "--export-eps", 12)
             || !strcmp(argv[i], "-A")
             || !strncmp(argv[i], "--export-pdf", 12)
-            || !strncmp(argv[i], "--export-pdf-latex", 18)
+            || !strncmp(argv[i], "--export-latex", 14)
 #ifdef WIN32
             || !strcmp(argv[i], "-M")
             || !strncmp(argv[i], "--export-emf", 12)
 #ifdef WIN32
             || !strcmp(argv[i], "-M")
             || !strncmp(argv[i], "--export-emf", 12)
@@ -1527,7 +1527,7 @@ static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime
         (*i)->set_param_bool("textToPath", FALSE);
     }
 
         (*i)->set_param_bool("textToPath", FALSE);
     }
 
-    if (sp_export_pdf_latex) {
+    if (sp_export_latex) {
         (*i)->set_param_bool("textToLaTeX", TRUE);
     } else {
         (*i)->set_param_bool("textToLaTeX", FALSE);
         (*i)->set_param_bool("textToLaTeX", TRUE);
     } else {
         (*i)->set_param_bool("textToLaTeX", FALSE);