summaryrefslogtreecommitdiff
path: root/libspectre/spectre-gs.c
diff options
context:
space:
mode:
authorCarlos Garcia Campos <carlosgc@gnome.org>2007-11-04 20:44:26 +0100
committerCarlos Garcia Campos <carlosgc@annarchy.freedesktop.org>2007-11-04 11:44:16 -0800
commit3419a054fc916aff188582bbaa5cee1f80778b43 (patch)
tree5f77b41d2b29018452da0a2e5223a4b177339efe /libspectre/spectre-gs.c
parent6e5849a2ab3143ecf78c7ee1b1df405429a3d946 (diff)
Add SpectreExporter to export to PS and PDF
Diffstat (limited to 'libspectre/spectre-gs.c')
-rw-r--r--libspectre/spectre-gs.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/libspectre/spectre-gs.c b/libspectre/spectre-gs.c
new file mode 100644
index 0000000..37fa003
--- /dev/null
+++ b/libspectre/spectre-gs.c
@@ -0,0 +1,261 @@
+/* This file is part of Libspectre.
+ *
+ * Copyright (C) 2007 Albert Astals Cid <aacid@kde.org>
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Libspectre 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, or (at your option)
+ * any later version.
+ *
+ * Libspectre 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "spectre-gs.h"
+#include "spectre-utils.h"
+
+/* ghostscript stuff */
+#include "ghostscript/iapi.h"
+#include "ghostscript/ierrors.h"
+
+#define BUFFER_SIZE 32768
+
+struct SpectreGS {
+ void *ghostscript_instance;
+};
+
+static int
+critic_error_code (int code)
+{
+ if (code >= 0)
+ return FALSE;
+
+ if (code <= -100) {
+ switch (code) {
+ case e_Fatal:
+ fprintf (stderr, "fatal internal error %d", code);
+ return TRUE;
+ break;
+
+ case e_ExecStackUnderflow:
+ fprintf (stderr, "stack overflow %d", code);
+ return TRUE;
+ break;
+
+ /* no error or not important */
+ default:
+ return FALSE;
+ }
+ } else {
+ const char *errors[] = { "", ERROR_NAMES };
+ int x = (-1) * code;
+
+ if (x < sizeof (errors) / sizeof (const char*)) {
+ fprintf (stderr, "%s %d\n", errors[x], code);
+ }
+ return TRUE;
+ }
+}
+
+static int
+spectre_gs_process (SpectreGS *gs,
+ const char *filename,
+ int x,
+ int y,
+ long begin,
+ long end)
+{
+ FILE *fd;
+ int error;
+ static char buf[BUFFER_SIZE];
+ unsigned int read;
+ int wrote;
+ size_t left = end - begin;
+ void *ghostscript_instance = gs->ghostscript_instance;
+
+ fd = fopen (filename, "r");
+ if (!fd) {
+ return FALSE;
+ }
+
+ fseek (fd, begin, SEEK_SET);
+
+ gsapi_run_string_begin (ghostscript_instance, 0, &error);
+ if (critic_error_code (error)) {
+ fclose (fd);
+ return FALSE;
+ }
+
+ if (x != 0 && y != 0) {
+ char *set;
+
+ set = _spectre_strdup_printf ("%d %d translate\n", -x, -y);
+ gsapi_run_string_continue (ghostscript_instance, set, strlen (set),
+ 0, &error);
+ free (set);
+ if (critic_error_code (error)) {
+ fclose (fd);
+ return FALSE;
+ }
+ }
+
+ while (left > 0 && !critic_error_code (error)) {
+ size_t to_read = BUFFER_SIZE;
+
+ if (left < to_read)
+ to_read = left;
+
+ read = fread (buf, sizeof (char), to_read, fd);
+ wrote = gsapi_run_string_continue (ghostscript_instance,
+ buf, read, 0, &error);
+ left -= read;
+ }
+
+ fclose (fd);
+ if (critic_error_code (error))
+ return FALSE;
+
+ gsapi_run_string_end (ghostscript_instance, 0, &error);
+ if (critic_error_code (error))
+ return FALSE;
+
+ return TRUE;
+}
+
+SpectreGS *
+spectre_gs_new (void)
+{
+ SpectreGS *gs;
+
+ gs = calloc (1, sizeof (SpectreGS));
+
+ return gs;
+}
+
+int
+spectre_gs_create_instance (SpectreGS *gs,
+ void *caller_handle)
+{
+ int error;
+
+ error = gsapi_new_instance (&gs->ghostscript_instance, caller_handle);
+
+ return !critic_error_code (error);
+}
+
+int
+spectre_gs_set_display_callback (SpectreGS *gs,
+ void *callback)
+{
+ int error;
+
+ error = gsapi_set_display_callback (gs->ghostscript_instance,
+ callback);
+ return !critic_error_code (error);
+}
+
+int
+spectre_gs_run (SpectreGS *gs,
+ int n_args,
+ char **args)
+{
+ int error;
+
+ error = gsapi_init_with_args (gs->ghostscript_instance, n_args, args);
+
+ return !critic_error_code (error);
+}
+
+int
+spectre_gs_send_string (SpectreGS *gs,
+ const char *str)
+{
+ int error;
+
+ gsapi_run_string_with_length (gs->ghostscript_instance,
+ str, strlen (str), 0, &error);
+
+ return !critic_error_code (error);
+}
+
+int
+spectre_gs_send_page (SpectreGS *gs,
+ struct document *doc,
+ unsigned int page_index)
+{
+ int urx, ury, llx, lly;
+
+ psgetpagebox (doc, page_index,
+ &urx, &ury, &llx, &lly);
+
+ if (!spectre_gs_process (gs,
+ doc->filename,
+ llx, lly,
+ doc->beginprolog,
+ doc->endprolog))
+ return FALSE;
+
+ if (!spectre_gs_process (gs,
+ doc->filename,
+ 0, 0,
+ doc->beginsetup,
+ doc->endsetup))
+ return FALSE;
+
+ if (doc->numpages > 0) {
+ if (!spectre_gs_process (gs,
+ doc->filename,
+ 0, 0,
+ doc->pages[page_index].begin,
+ doc->pages[page_index].end))
+ return FALSE;
+ }
+
+ if (!spectre_gs_process (gs,
+ doc->filename,
+ 0, 0,
+ doc->begintrailer,
+ doc->endtrailer))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+spectre_gs_cleanup (SpectreGS *gs,
+ SpectreGSCleanupFlag flag)
+{
+ if (gs->ghostscript_instance == NULL)
+ return;
+
+ if (flag & CLEANUP_EXIT)
+ gsapi_exit (gs->ghostscript_instance);
+
+ if (flag & CLEANUP_DELETE_INSTANCE)
+ gsapi_delete_instance (gs->ghostscript_instance);
+
+ gs->ghostscript_instance = NULL;
+}
+
+void
+spectre_gs_free (SpectreGS *gs)
+{
+ if (!gs)
+ return;
+
+ spectre_gs_cleanup (gs,
+ CLEANUP_DELETE_INSTANCE |
+ CLEANUP_EXIT);
+ free (gs);
+}