1
/* Ghostscript widget for GTK/GNOME
3
* Copyright (C) 1998 - 2005 the Free Software Foundation
5
* Authors: Jonathan Blandford, Jaka Mocnik, Carlos Garcia Campos
7
* Based on code by: Federico Mena (Quartic), Szekeres Istvan (Pista)
9
* This library is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU Library General Public
11
* License as published by the Free Software Foundation; either
12
* version 2 of the License, or (at your option) any later version.
14
* This library is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* Library General Public License for more details.
19
* You should have received a copy of the GNU Library General Public
20
* License along with this library; if not, write to the
21
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22
* Boston, MA 02111-1307, USA.
27
#include <glib/gstdio.h>
28
#include <glib/gi18n.h>
29
#include <gdk/gdkpixbuf.h>
33
#include "ps-document.h"
34
#include "ps-interpreter.h"
37
#include "gsdefaults.h"
38
#include "ev-file-exporter.h"
39
#include "ev-async-renderer.h"
40
#include "ev-document-thumbnails.h"
41
#include "ev-document-misc.h"
48
gboolean structured_doc;
52
/* Document Thumbnails */
53
PSInterpreter *thumbs_gs;
55
EvRenderContext *thumbs_rc;
60
gint *ps_export_pagelist;
61
gchar *ps_export_filename;
64
struct _PSDocumentClass {
65
GObjectClass parent_class;
68
static void ps_document_document_iface_init (EvDocumentIface *iface);
69
static void ps_document_file_exporter_iface_init (EvFileExporterIface *iface);
70
static void ps_async_renderer_iface_init (EvAsyncRendererIface *iface);
71
static void ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
73
static void ps_interpreter_page_rendered (PSInterpreter *gs,
75
PSDocument *ps_document);
77
EV_BACKEND_REGISTER_WITH_CODE (PSDocument, ps_document,
79
EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
80
ps_document_document_thumbnails_iface_init);
81
EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
82
ps_document_file_exporter_iface_init);
83
EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_ASYNC_RENDERER,
84
ps_async_renderer_iface_init);
89
ps_document_init (PSDocument *ps_document)
94
ps_document_dispose (GObject *object)
96
PSDocument *ps_document = PS_DOCUMENT (object);
98
if (ps_document->gs) {
99
g_object_unref (ps_document->gs);
100
ps_document->gs = NULL;
103
if (ps_document->thumbs_gs) {
104
g_object_unref (ps_document->thumbs_gs);
105
ps_document->thumbs_gs = NULL;
108
if (ps_document->filename) {
109
g_free (ps_document->filename);
110
ps_document->filename = NULL;
113
if (ps_document->doc) {
114
psfree (ps_document->doc);
115
ps_document->doc = NULL;
118
if (ps_document->thumbnail) {
119
g_object_unref (ps_document->thumbnail);
120
ps_document->thumbnail = NULL;
123
if (ps_document->thumbs_mutex) {
124
g_mutex_free (ps_document->thumbs_mutex);
125
ps_document->thumbs_mutex = NULL;
128
if (ps_document->thumbs_cond) {
129
g_cond_free (ps_document->thumbs_cond);
130
ps_document->thumbs_cond = NULL;
133
if (ps_document->thumbs_rc) {
134
g_object_unref (ps_document->thumbs_rc);
135
ps_document->thumbs_rc = NULL;
138
G_OBJECT_CLASS (ps_document_parent_class)->dispose (object);
142
ps_document_class_init (PSDocumentClass *klass)
144
GObjectClass *object_class;
146
object_class = G_OBJECT_CLASS (klass);
148
object_class->dispose = ps_document_dispose;
151
/* EvDocumentIface */
153
document_load (PSDocument *ps_document, const gchar *fname, GError **error)
157
ps_document->filename = g_strdup (fname);
160
* We need to make sure that the file is loadable/exists!
161
* otherwise we want to exit without loading new stuff...
163
if (!g_file_test (fname, G_FILE_TEST_IS_REGULAR)) {
166
filename_dsp = g_filename_display_name (fname);
170
_("Cannot open file “%s”."),
172
g_free (filename_dsp);
177
if ((fd = fopen (ps_document->filename, "r")) == NULL) {
180
filename_dsp = g_filename_display_name (fname);
184
_("Cannot open file “%s”."),
186
g_free (filename_dsp);
191
/* we grab the vital statistics!!! */
192
ps_document->doc = psscan (fd, TRUE, ps_document->filename);
194
if (!ps_document->doc)
197
ps_document->structured_doc =
198
((!ps_document->doc->epsf && ps_document->doc->numpages > 0) ||
199
(ps_document->doc->epsf && ps_document->doc->numpages > 1));
201
ps_document->gs = ps_interpreter_new (ps_document->filename,
203
g_signal_connect (G_OBJECT (ps_document->gs), "page_rendered",
204
G_CALLBACK (ps_interpreter_page_rendered),
205
(gpointer) ps_document);
211
ps_document_load (EvDocument *document,
219
filename = g_filename_from_uri (uri, NULL, error);
223
gs_path = g_find_program_in_path ("gs");
227
filename_dsp = g_filename_display_name (filename);
231
_("Failed to load document “%s”. Ghostscript interpreter was not found in path"),
233
g_free (filename_dsp);
240
result = document_load (PS_DOCUMENT (document), filename, error);
241
if (!result && !(*error)) {
244
filename_dsp = g_filename_display_name (filename);
248
_("Failed to load document “%s”"),
250
g_free (filename_dsp);
259
save_document (PSDocument *document, const char *filename)
261
gboolean result = TRUE;
262
GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
266
src_file = fopen (document->filename, "r");
268
struct stat stat_rec;
270
if (stat (document->filename, &stat_rec) == 0) {
271
pscopy (src_file, sink, 0, stat_rec.st_size - 1);
277
buf = gtk_gs_doc_sink_get_buffer (sink);
282
f = fopen (filename, "w");
291
gtk_gs_doc_sink_free (sink);
298
save_page_list (PSDocument *document, int *page_list, const char *filename)
300
gboolean result = TRUE;
301
GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
305
pscopydoc (sink, document->filename,
306
document->doc, page_list);
308
buf = gtk_gs_doc_sink_get_buffer (sink);
310
f = fopen (filename, "w");
319
gtk_gs_doc_sink_free (sink);
326
ps_document_save (EvDocument *document,
330
PSDocument *ps = PS_DOCUMENT (document);
334
filename = g_filename_from_uri (uri, NULL, error);
338
result = save_document (ps, filename);
346
ps_document_get_n_pages (EvDocument *document)
348
PSDocument *ps = PS_DOCUMENT (document);
350
if (!ps->filename || !ps->doc) {
354
return ps->structured_doc ? ps->doc->numpages : 1;
358
ps_document_get_page_rotation (PSDocument *ps_document,
361
gint rotation = GTK_GS_ORIENTATION_NONE;
363
g_assert (ps_document->doc != NULL);
365
if (ps_document->structured_doc) {
366
if (ps_document->doc->pages[page].orientation != GTK_GS_ORIENTATION_NONE)
367
rotation = ps_document->doc->pages[page].orientation;
369
rotation = ps_document->doc->default_page_orientation;
372
if (rotation == GTK_GS_ORIENTATION_NONE)
373
rotation = ps_document->doc->orientation;
375
if (rotation == GTK_GS_ORIENTATION_NONE)
376
rotation = GTK_GS_ORIENTATION_PORTRAIT;
382
ps_document_get_page_size (EvDocument *document,
387
PSDocument *ps_document = PS_DOCUMENT (document);
388
int urx, ury, llx, lly;
389
gdouble pwidth, pheight;
390
gdouble page_width, page_height;
393
psgetpagebox (ps_document->doc, page, &urx, &ury, &llx, &lly);
395
pwidth = (urx - llx) + 0.5;
396
pheight = (ury - lly) + 0.5;
398
rotate = ps_document_get_page_rotation (ps_document, page);
399
if (rotate == 90 || rotate == 270) {
400
page_height = pwidth;
401
page_width = pheight;
404
page_height = pheight;
412
*height = page_height;
416
static EvDocumentInfo *
417
ps_document_get_info (EvDocument *document)
419
EvDocumentInfo *info;
420
PSDocument *ps = PS_DOCUMENT (document);
421
int urx, ury, llx, lly;
423
info = g_new0 (EvDocumentInfo, 1);
424
info->fields_mask = EV_DOCUMENT_INFO_TITLE |
425
EV_DOCUMENT_INFO_FORMAT |
426
EV_DOCUMENT_INFO_CREATOR |
427
EV_DOCUMENT_INFO_N_PAGES |
428
EV_DOCUMENT_INFO_PAPER_SIZE;
430
info->title = g_strdup (ps->doc->title);
431
info->format = ps->doc->epsf ? g_strdup (_("Encapsulated PostScript"))
432
: g_strdup (_("PostScript"));
433
info->creator = g_strdup (ps->doc->creator);
434
info->n_pages = ev_document_get_n_pages (document);
436
psgetpagebox (PS_DOCUMENT (document)->doc, 0, &urx, &ury, &llx, &lly);
438
info->paper_width = (urx - llx) / 72.0f * 25.4f;
439
info->paper_height = (ury - lly) / 72.0f * 25.4f;
445
ps_document_document_iface_init (EvDocumentIface *iface)
447
iface->load = ps_document_load;
448
iface->save = ps_document_save;
449
iface->get_n_pages = ps_document_get_n_pages;
450
iface->get_page_size = ps_document_get_page_size;
451
iface->get_info = ps_document_get_info;
454
/* EvAsyncRendererIface */
456
ps_interpreter_page_rendered (PSInterpreter *gs,
458
PSDocument *ps_document)
460
g_signal_emit_by_name (ps_document, "render_finished", pixbuf);
464
ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer,
469
PSDocument *ps_document = PS_DOCUMENT (renderer);
471
g_return_if_fail (PS_IS_INTERPRETER (ps_document->gs));
473
rotation = (rotation + ps_document_get_page_rotation (ps_document, page)) % 360;
475
ps_interpreter_render_page (ps_document->gs, page, scale, rotation);
479
ps_async_renderer_iface_init (EvAsyncRendererIface *iface)
481
iface->render_pixbuf = ps_async_renderer_render_pixbuf;
484
/* EvDocumentThumbnailsIface */
486
ps_interpreter_thumbnail_rendered (PSInterpreter *gs,
488
PSDocument *ps_document)
490
if (ps_document->thumbnail)
491
g_object_unref (ps_document->thumbnail);
492
ps_document->thumbnail = g_object_ref (pixbuf);
494
g_cond_broadcast (ps_document->thumbs_cond);
498
ps_document_render_thumbnail (PSDocument *ps_document)
500
ps_interpreter_render_page (ps_document->thumbs_gs,
501
ps_document->thumbs_rc->page,
502
ps_document->thumbs_rc->scale,
503
ps_document->thumbs_rc->rotation);
509
ps_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
513
PSDocument *ps_document;
514
GdkPixbuf *pixbuf = NULL;
516
ps_document = PS_DOCUMENT (document_thumbnails);
518
g_return_val_if_fail (ps_document->filename != NULL, NULL);
519
g_return_val_if_fail (ps_document->doc != NULL, NULL);
521
if (!ps_document->thumbs_gs) {
522
ps_document->thumbs_gs = ps_interpreter_new (ps_document->filename,
524
g_signal_connect (G_OBJECT (ps_document->thumbs_gs), "page_rendered",
525
G_CALLBACK (ps_interpreter_thumbnail_rendered),
526
(gpointer) ps_document);
529
if (!ps_document->thumbs_mutex)
530
ps_document->thumbs_mutex = g_mutex_new ();
531
ps_document->thumbs_cond = g_cond_new ();
533
if (ps_document->thumbs_rc)
534
g_object_unref (ps_document->thumbs_rc);
535
ps_document->thumbs_rc = g_object_ref (rc);
537
ev_document_doc_mutex_unlock ();
538
g_mutex_lock (ps_document->thumbs_mutex);
539
g_idle_add ((GSourceFunc)ps_document_render_thumbnail, ps_document);
540
g_cond_wait (ps_document->thumbs_cond, ps_document->thumbs_mutex);
541
g_cond_free (ps_document->thumbs_cond);
542
ps_document->thumbs_cond = NULL;
543
g_mutex_unlock (ps_document->thumbs_mutex);
544
ev_document_doc_mutex_lock ();
546
pixbuf = ps_document->thumbnail;
547
ps_document->thumbnail = NULL;
550
GdkPixbuf *border_pixbuf;
552
border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
553
g_object_unref (pixbuf);
554
pixbuf = border_pixbuf;
561
ps_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
566
PSDocument *ps_document;
567
gdouble page_width, page_height;
569
ps_document = PS_DOCUMENT (document_thumbnails);
571
ps_document_get_page_size (EV_DOCUMENT (ps_document),
573
&page_width, &page_height);
575
if (rc->rotation == 90 || rc->rotation == 270) {
576
*width = (gint) (page_height * rc->scale);
577
*height = (gint) (page_width * rc->scale);
579
*width = (gint) (page_width * rc->scale);
580
*height = (gint) (page_height * rc->scale);
585
ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
587
iface->get_thumbnail = ps_document_thumbnails_get_thumbnail;
588
iface->get_dimensions = ps_document_thumbnails_get_dimensions;
591
/* EvFileExporterIface */
593
ps_document_file_exporter_begin (EvFileExporter *exporter,
594
EvFileExporterContext *fc)
596
PSDocument *document = PS_DOCUMENT (exporter);
598
if (document->structured_doc) {
599
g_free (document->ps_export_pagelist);
601
document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
604
document->ps_export_filename = g_strdup (fc->filename);
608
ps_document_file_exporter_do_page (EvFileExporter *exporter,
611
PSDocument *document = PS_DOCUMENT (exporter);
613
if (document->structured_doc) {
614
document->ps_export_pagelist[rc->page] = 1;
619
ps_document_file_exporter_end (EvFileExporter *exporter)
621
PSDocument *document = PS_DOCUMENT (exporter);
623
if (!document->structured_doc) {
624
save_document (document, document->ps_export_filename);
626
save_page_list (document, document->ps_export_pagelist,
627
document->ps_export_filename);
628
g_free (document->ps_export_pagelist);
629
g_free (document->ps_export_filename);
630
document->ps_export_pagelist = NULL;
631
document->ps_export_filename = NULL;
635
static EvFileExporterCapabilities
636
ps_document_file_exporter_get_capabilities (EvFileExporter *exporter)
638
return EV_FILE_EXPORTER_CAN_PAGE_SET |
639
EV_FILE_EXPORTER_CAN_GENERATE_PS;
643
ps_document_file_exporter_iface_init (EvFileExporterIface *iface)
645
iface->begin = ps_document_file_exporter_begin;
646
iface->do_page = ps_document_file_exporter_do_page;
647
iface->end = ps_document_file_exporter_end;
648
iface->get_capabilities = ps_document_file_exporter_get_capabilities;