#include "ps-document.h"
#include "ev-debug.h"
#include "gsdefaults.h"
-#include "ev-ps-exporter.h"
+#include "ev-file-exporter.h"
#include "ev-async-renderer.h"
#define MAX_BUFSIZE 1024
static gboolean broken_pipe = FALSE;
/* Forward declarations */
-static void ps_document_init (PSDocument *gs);
-static void ps_document_class_init (PSDocumentClass *klass);
-static void send_ps (PSDocument *gs,
- long begin,
- unsigned int len,
- gboolean close);
-static void output (gpointer data,
- gint source,
- GdkInputCondition condition);
-static void input (gpointer data,
- gint source,
- GdkInputCondition condition);
-static void stop_interpreter (PSDocument *gs);
-static gint start_interpreter (PSDocument *gs);
-static void ps_document_document_iface_init (EvDocumentIface *iface);
-static void ps_document_ps_exporter_iface_init (EvPSExporterIface *iface);
-static void ps_async_renderer_iface_init (EvAsyncRendererIface *iface);
+static void ps_document_init (PSDocument *gs);
+static void ps_document_class_init (PSDocumentClass *klass);
+static void send_ps (PSDocument *gs,
+ long begin,
+ unsigned int len,
+ gboolean close);
+static void output (gpointer data,
+ gint source,
+ GdkInputCondition condition);
+static void input (gpointer data,
+ gint source,
+ GdkInputCondition condition);
+static void stop_interpreter (PSDocument *gs);
+static gint start_interpreter (PSDocument *gs);
+static void ps_document_document_iface_init (EvDocumentIface *iface);
+static void ps_document_file_exporter_iface_init (EvFileExporterIface *iface);
+static void ps_async_renderer_iface_init (EvAsyncRendererIface *iface);
G_DEFINE_TYPE_WITH_CODE (PSDocument, ps_document, G_TYPE_OBJECT,
{
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
ps_document_document_iface_init);
- G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER,
- ps_document_ps_exporter_iface_init);
+ G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
+ ps_document_file_exporter_iface_init);
G_IMPLEMENT_INTERFACE (EV_TYPE_ASYNC_RENDERER,
ps_async_renderer_iface_init);
});
gs->ps_export_pagelist = NULL;
gs->ps_export_filename = NULL;
-
- gs->orientation = GTK_GS_ORIENTATION_NONE;
}
static void
GdkColormap *cmap;
GdkPixbuf *pixbuf;
int width, height;
+
+ if (gs->pstarget == NULL)
+ return;
cmap = gdk_window_get_colormap (gs->pstarget);
gdk_drawable_get_size (gs->bpixmap, &width, &height);
+ LOG ("Get from drawable\n");
pixbuf = gdk_pixbuf_get_from_drawable (NULL, gs->bpixmap, cmap,
0, 0, 0, 0,
width, height);
+ LOG ("Get from drawable done\n");
g_signal_emit_by_name (gs, "render_finished", pixbuf);
g_object_unref (pixbuf);
}
gs->busy = FALSE;
push_pixbuf (gs);
+ LOG ("Pixbuf pushed");
}
return TRUE;
}
}
-static float
-get_xdpi (PSDocument *gs)
-{
- return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
-}
-
-static float
-get_ydpi (PSDocument *gs)
-{
- return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
-}
-
static void
-setup_pixmap (PSDocument *gs, int page, double scale)
+setup_pixmap (PSDocument *gs, int page, double scale, int rotation)
{
GdkGC *fill;
GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF }; /* pixel, r, g, b */
GdkColormap *colormap;
double width, height;
int pixmap_width, pixmap_height;
+
+ if (gs->pstarget == NULL)
+ return;
ev_document_get_page_size (EV_DOCUMENT (gs), page, &width, &height);
- pixmap_width = width * scale + 0.5;
- pixmap_height = height * scale + 0.5;
+
+ if (rotation == 90 || rotation == 270) {
+ pixmap_height = width * scale + 0.5;
+ pixmap_width = height * scale + 0.5;
+ } else {
+ pixmap_width = width * scale + 0.5;
+ pixmap_height = height * scale + 0.5;
+ }
if(gs->bpixmap) {
int w, h;
*lly = new_lly;
}
-static int
-get_page_orientation (PSDocument *gs, int page)
-{
- int orientation;
-
- orientation = GTK_GS_ORIENTATION_NONE;
-
- if (gs->structured_doc) {
- orientation = gs->doc->pages[page].orientation;
- }
- if (orientation == GTK_GS_ORIENTATION_NONE) {
- orientation = gs->doc->default_page_orientation;
- }
- if (orientation == GTK_GS_ORIENTATION_NONE) {
- orientation = gs->doc->orientation;
- }
- if (orientation == GTK_GS_ORIENTATION_NONE) {
- orientation = GTK_GS_ORIENTATION_PORTRAIT;
- }
- if (gs->orientation != GTK_GS_ORIENTATION_NONE) {
- orientation = gs->orientation;
- }
-
- return orientation;
-}
-
static void
-setup_page (PSDocument *gs, int page, double scale)
+setup_page (PSDocument *gs, int page, double scale, int rotation)
{
gchar *buf;
- int urx, ury, llx, lly, orientation;
- char scaled_xdpi[G_ASCII_DTOSTR_BUF_SIZE];
- char scaled_ydpi[G_ASCII_DTOSTR_BUF_SIZE];
+ char scaled_dpi[G_ASCII_DTOSTR_BUF_SIZE];
+ int urx, ury, llx, lly;
LOG ("Setup the page");
get_page_box (gs, page, &urx, &ury, &llx, &lly);
- orientation = get_page_orientation (gs, page);
- g_ascii_dtostr (scaled_xdpi, G_ASCII_DTOSTR_BUF_SIZE, get_xdpi (gs) * scale);
- g_ascii_dtostr (scaled_ydpi, G_ASCII_DTOSTR_BUF_SIZE, get_ydpi (gs) * scale);
+ g_ascii_dtostr (scaled_dpi, G_ASCII_DTOSTR_BUF_SIZE, 72.0 * scale);
buf = g_strdup_printf ("%ld %d %d %d %d %d %s %s %d %d %d %d",
- 0L, orientation * 90, llx, lly, urx, ury,
- scaled_xdpi, scaled_ydpi,
+ 0L, rotation, llx, lly, urx, ury,
+ scaled_dpi, scaled_dpi,
0, 0, 0, 0);
LOG ("GS property %s", buf);
#define NUM_GS_ARGS (NUM_ARGS - 20)
#define NUM_ALPHA_ARGS 10
- char *argv[NUM_ARGS], *dir, *gv_env;
+ char *argv[NUM_ARGS], *dir, *gv_env, *gs_path;
char **gs_args, **alpha_args = NULL;
+ char **gv_env_vars = NULL;
int argc = 0, i;
LOG ("Start the interpreter");
stop_interpreter(gs);
/* set up the args... */
- gs_args = g_strsplit (gtk_gs_defaults_get_interpreter_cmd (), " ", NUM_GS_ARGS);
+ gs_path = g_find_program_in_path ("gs");
+ gs_args = g_strsplit (gs_path, " ", NUM_GS_ARGS);
+ g_free (gs_path);
for(i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
argv[argc] = gs_args[i];
}
return -1;
}
- gv_env = g_strdup_printf ("GHOSTVIEW=%ld %ld",
+ gv_env = g_strdup_printf ("GHOSTVIEW=%ld %ld;DISPLAY=%s",
gdk_x11_drawable_get_xid (gs->pstarget),
- gdk_x11_drawable_get_xid (gs->bpixmap));
+ gdk_x11_drawable_get_xid (gs->bpixmap),
+ gdk_display_get_name (gdk_drawable_get_display (gs->pstarget)));
LOG ("Launching ghostview with env %s", gv_env);
gs->interpreter_pid = fork ();
}
}
- putenv(gv_env);
+ gv_env_vars = g_strsplit (gv_env, ";", -1);
+ g_free (gv_env);
+ for (i = 0; gv_env_vars[i]; i++) {
+ putenv (gv_env_vars[i]);
+ }
/* change to directory where the input file is. This helps
* with postscript-files which include other files using
/* Notify error */
g_critical ("Unable to execute [%s]\n", argv[0]);
g_strfreev (gs_args);
- g_free (gv_env);
g_strfreev (alpha_args);
+ g_strfreev (gv_env_vars);
_exit (1);
break;
default: /* parent */
/* sucessfully uncompressed file */
gs->gs_filename_unc = filename_unc;
} else {
- gchar *utf8 = NULL;
+ gchar *filename_dsp;
gchar *msg;
/* report error */
- utf8 = g_locale_to_utf8 (gs->gs_filename, -1, NULL, NULL, NULL);
-
- if (utf8) {
- msg = g_strdup_printf (_("Error while decompressing file %s:\n"), utf8);
- } else {
- msg = g_strdup (_("Error while decompressing file\n"));
- }
-
- g_free (utf8);
+ filename_dsp = g_filename_display_name (gs->gs_filename);
+ msg = g_strdup_printf (_("Error while decompressing file “%s”:\n"), filename_dsp);
+ g_free (filename_dsp);
interpreter_failed (gs, msg);
g_free (msg);
gchar *filename = NULL;
if (!file_readable(fname)) {
- gchar *utf8 = NULL;
+ gchar *filename_dsp;
gchar *msg;
- utf8 = g_locale_to_utf8 (fname, -1, NULL, NULL, NULL);
-
- if (utf8) {
- msg = g_strdup_printf (_("Cannot open file %s.\n"), utf8);
- } else {
- msg = g_strdup (_("Cannot open file.\n"));
- }
-
- g_free (utf8);
+ filename_dsp = g_filename_display_name (fname);
+ msg = g_strdup_printf (_("Cannot open file “%s”.\n"), filename_dsp);
+ g_free (filename_dsp);
interpreter_failed (gs, msg);
g_free (msg);
static gboolean
ps_document_next_page (PSDocument *gs)
{
- XEvent event;
+ XEvent event;
+ GdkScreen *screen;
+ GdkDisplay *display;
+ Display *dpy;
LOG ("Make ghostscript render next page");
gs->busy = TRUE;
+ screen = gtk_window_get_screen (GTK_WINDOW (gs->target_window));
+ display = gdk_screen_get_display (screen);
+ dpy = gdk_x11_display_get_xdisplay (display);
+
event.xclient.type = ClientMessage;
- event.xclient.display = gdk_display;
+ event.xclient.display = dpy;
event.xclient.window = gs->message_window;
- event.xclient.message_type = gdk_x11_atom_to_xatom(gs_class->next_atom);
+ event.xclient.message_type =
+ gdk_x11_atom_to_xatom_for_display (display,
+ gs_class->next_atom);
event.xclient.format = 32;
gdk_error_trap_push ();
- XSendEvent (gdk_display, gs->message_window, FALSE, 0, &event);
+ XSendEvent (dpy, gs->message_window, FALSE, 0, &event);
gdk_flush ();
gdk_error_trap_pop ();
const char *uri,
GError **error)
{
- gboolean result;
char *filename;
+ char *gs_path;
+ gboolean result;
filename = g_filename_from_uri (uri, NULL, error);
if (!filename)
return FALSE;
- result = document_load (PS_DOCUMENT (document), filename);
- if (!result) {
- gchar *utf8 = NULL;
-
- utf8 = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
-
- if (utf8) {
- g_set_error (error, G_FILE_ERROR,
- G_FILE_ERROR_FAILED,
- _("Failed to load document '%s'"),
- utf8);
- } else {
+ gs_path = g_find_program_in_path ("gs");
+ if (!gs_path) {
+ gchar *filename_dsp;
+ filename_dsp = g_filename_display_name (filename);
+ g_set_error(error,
+ G_FILE_ERROR,
+ G_FILE_ERROR_NOENT,
+ _("Failed to load document “%s”. Ghostscript interpreter was not found in path"),
+ filename);
+ g_free (filename_dsp);
+ result = FALSE;
+ } else {
+ result = document_load (PS_DOCUMENT (document), filename);
+ if (!result) {
+ gchar *filename_dsp;
+ filename_dsp = g_filename_display_name (filename);
+
g_set_error (error, G_FILE_ERROR,
G_FILE_ERROR_FAILED,
- _("Failed to load document"));
+ _("Failed to load document “%s”"),
+ filename_dsp);
+ g_free (filename_dsp);
+ }
+ g_free (gs_path);
+ }
+ g_free (filename);
+
+ return result;
+}
+
+static gboolean
+save_document (PSDocument *document, const char *filename)
+{
+ gboolean result = TRUE;
+ GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
+ FILE *f, *src_file;
+ gchar *buf;
+
+ src_file = fopen (PS_DOCUMENT_GET_PS_FILE(document), "r");
+ if (src_file) {
+ struct stat stat_rec;
+
+ if (stat (PS_DOCUMENT_GET_PS_FILE(document), &stat_rec) == 0) {
+ pscopy (src_file, sink, 0, stat_rec.st_size - 1);
}
- g_free (utf8);
+ fclose (src_file);
+ }
+
+ buf = gtk_gs_doc_sink_get_buffer (sink);
+ if (buf == NULL) {
+ return FALSE;
+ }
+
+ f = fopen (filename, "w");
+ if (f) {
+ fputs (buf, f);
+ fclose (f);
+ } else {
+ result = FALSE;
}
- g_free (filename);
+ g_free (buf);
+ gtk_gs_doc_sink_free (sink);
+ g_free (sink);
return result;
}
GError **error)
{
PSDocument *ps = PS_DOCUMENT (document);
- int *page_list;
gboolean result;
- int i;
char *filename;
filename = g_filename_from_uri (uri, NULL, error);
if (!filename)
return FALSE;
- page_list = g_new0 (int, ps->doc->numpages);
- for (i = 0; i < ps->doc->numpages; i++) {
- page_list[i] = 1;
- }
-
- result = save_page_list (ps, page_list, filename);
+ result = save_document (ps, filename);
- g_free (page_list);
g_free (filename);
return result;
double *height)
{
PSDocument *gs = PS_DOCUMENT (document);
- int w, h;
- int urx, ury, llx, lly, orientation;
-
- get_page_box (PS_DOCUMENT (document), page, &urx, &ury, &llx, &lly);
- orientation = get_page_orientation (PS_DOCUMENT (document), page);
+ int urx, ury, llx, lly;
- switch (orientation) {
- case GTK_GS_ORIENTATION_PORTRAIT:
- case GTK_GS_ORIENTATION_UPSIDEDOWN:
- w = (urx - llx) / 72.0 * get_xdpi (gs) + 0.5;
- h = (ury - lly) / 72.0 * get_ydpi (gs) + 0.5;
- break;
- case GTK_GS_ORIENTATION_LANDSCAPE:
- case GTK_GS_ORIENTATION_SEASCAPE:
- w = (ury - lly) / 72.0 * get_xdpi (gs) + 0.5;
- h = (urx - llx) / 72.0 * get_ydpi (gs) + 0.5;
- break;
- default:
- w = h = 0;
- g_assert_not_reached ();
- break;
- }
+ get_page_box (gs, page, &urx, &ury, &llx, &lly);
if (width) {
- *width = w;
+ *width = (urx - llx) + 0.5;
}
if (height) {
- *height = h;
+ *height = (ury - lly) + 0.5;
}
}
}
static void
-ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer, int page, double scale)
+ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer, int page, double scale, int rotation)
{
PSDocument *gs = PS_DOCUMENT (renderer);
gs);
}
- setup_pixmap (gs, page, scale);
- setup_page (gs, page, scale);
+ setup_pixmap (gs, page, scale, rotation);
+ setup_page (gs, page, scale, rotation);
render_page (gs, page);
}
{
EvDocumentInfo *info;
PSDocument *ps = PS_DOCUMENT (document);
+ int urx, ury, llx, lly;
info = g_new0 (EvDocumentInfo, 1);
info->fields_mask = EV_DOCUMENT_INFO_TITLE |
EV_DOCUMENT_INFO_FORMAT |
EV_DOCUMENT_INFO_CREATOR |
- EV_DOCUMENT_INFO_N_PAGES;
+ EV_DOCUMENT_INFO_N_PAGES |
+ EV_DOCUMENT_INFO_PAPER_SIZE;
+
info->title = g_strdup (ps->doc->title);
info->format = ps->doc->epsf ? g_strdup (_("Encapsulated PostScript"))
: g_strdup (_("PostScript"));
info->creator = g_strdup (ps->doc->creator);
info->n_pages = ev_document_get_n_pages (document);
+
+ get_page_box (PS_DOCUMENT (document), 0, &urx, &ury, &llx, &lly);
+
+ info->paper_width = (urx - llx) / 72.0f * 25.4f;
+ info->paper_height = (ury - lly) / 72.0f * 25.4f;
return info;
}
iface->render_pixbuf = ps_async_renderer_render_pixbuf;
}
+static gboolean
+ps_document_file_exporter_format_supported (EvFileExporter *exporter,
+ EvFileExporterFormat format)
+{
+ return (format == EV_FILE_FORMAT_PS);
+}
+
static void
-ps_document_ps_export_begin (EvPSExporter *exporter, const char *filename,
- int first_page, int last_page,
- double width, double height, gboolean duplex)
+ps_document_file_exporter_begin (EvFileExporter *exporter,
+ EvFileExporterFormat format,
+ const char *filename,
+ int first_page,
+ int last_page,
+ double width,
+ double height,
+ gboolean duplex)
{
PSDocument *document = PS_DOCUMENT (exporter);
- g_free (document->ps_export_pagelist);
+ if (document->structured_doc) {
+ g_free (document->ps_export_pagelist);
- document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
+ document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
+ }
+
document->ps_export_filename = g_strdup (filename);
}
static void
-ps_document_ps_export_do_page (EvPSExporter *exporter, EvRenderContext *rc)
+ps_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc)
{
PSDocument *document = PS_DOCUMENT (exporter);
- document->ps_export_pagelist[rc->page] = 1;
+ if (document->structured_doc) {
+ document->ps_export_pagelist[rc->page] = 1;
+ }
}
static void
-ps_document_ps_export_end (EvPSExporter *exporter)
+ps_document_file_exporter_end (EvFileExporter *exporter)
{
PSDocument *document = PS_DOCUMENT (exporter);
- save_page_list (document, document->ps_export_pagelist,
- document->ps_export_filename);
-
- g_free (document->ps_export_pagelist);
- g_free (document->ps_export_filename);
- document->ps_export_pagelist = NULL;
- document->ps_export_filename = NULL;
+ if (!document->structured_doc) {
+ save_document (document, document->ps_export_filename);
+ } else {
+ save_page_list (document, document->ps_export_pagelist,
+ document->ps_export_filename);
+ g_free (document->ps_export_pagelist);
+ g_free (document->ps_export_filename);
+ document->ps_export_pagelist = NULL;
+ document->ps_export_filename = NULL;
+ }
}
static void
-ps_document_ps_exporter_iface_init (EvPSExporterIface *iface)
+ps_document_file_exporter_iface_init (EvFileExporterIface *iface)
{
- iface->begin = ps_document_ps_export_begin;
- iface->do_page = ps_document_ps_export_do_page;
- iface->end = ps_document_ps_export_end;
+ iface->format_supported = ps_document_file_exporter_format_supported;
+ iface->begin = ps_document_file_exporter_begin;
+ iface->do_page = ps_document_file_exporter_do_page;
+ iface->end = ps_document_file_exporter_end;
}