3 #include "ev-job-queue.h"
4 #include "ev-document-thumbnails.h"
5 #include "ev-document-links.h"
6 #include "ev-document-images.h"
7 #include "ev-document-forms.h"
8 #include "ev-file-exporter.h"
9 #include "ev-document-factory.h"
10 #include "ev-document-misc.h"
11 #include "ev-file-helpers.h"
12 #include "ev-document-fonts.h"
13 #include "ev-async-renderer.h"
16 #include <glib/gstdio.h>
17 #include <glib/gi18n.h>
20 static void ev_job_init (EvJob *job);
21 static void ev_job_class_init (EvJobClass *class);
22 static void ev_job_links_init (EvJobLinks *job);
23 static void ev_job_links_class_init (EvJobLinksClass *class);
24 static void ev_job_render_init (EvJobRender *job);
25 static void ev_job_render_class_init (EvJobRenderClass *class);
26 static void ev_job_thumbnail_init (EvJobThumbnail *job);
27 static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class);
28 static void ev_job_load_init (EvJobLoad *job);
29 static void ev_job_load_class_init (EvJobLoadClass *class);
30 static void ev_job_save_init (EvJobSave *job);
31 static void ev_job_save_class_init (EvJobSaveClass *class);
32 static void ev_job_print_init (EvJobPrint *job);
33 static void ev_job_print_class_init (EvJobPrintClass *class);
45 static guint job_signals[LAST_SIGNAL] = { 0 };
46 static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
48 G_DEFINE_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
49 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
50 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
51 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
52 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
53 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
54 G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
55 G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
57 static void ev_job_init (EvJob *job) { /* Do Nothing */ }
60 ev_job_dispose (GObject *object)
64 job = EV_JOB (object);
67 g_object_unref (job->document);
71 (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
75 ev_job_class_init (EvJobClass *class)
79 oclass = G_OBJECT_CLASS (class);
81 oclass->dispose = ev_job_dispose;
83 job_signals [FINISHED] =
84 g_signal_new ("finished",
87 G_STRUCT_OFFSET (EvJobClass, finished),
89 g_cclosure_marshal_VOID__VOID,
94 static void ev_job_links_init (EvJobLinks *job) { /* Do Nothing */ }
97 ev_job_links_dispose (GObject *object)
101 job = EV_JOB_LINKS (object);
104 g_object_unref (job->model);
108 (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
112 ev_job_links_class_init (EvJobLinksClass *class)
114 GObjectClass *oclass;
116 oclass = G_OBJECT_CLASS (class);
118 oclass->dispose = ev_job_links_dispose;
122 static void ev_job_render_init (EvJobRender *job) { /* Do Nothing */ }
125 ev_job_render_dispose (GObject *object)
129 job = EV_JOB_RENDER (object);
132 cairo_surface_destroy (job->surface);
137 g_object_unref (job->rc);
141 if (job->selection) {
142 cairo_surface_destroy (job->selection);
143 job->selection = NULL;
146 if (job->selection_region) {
147 gdk_region_destroy (job->selection_region);
148 job->selection_region = NULL;
151 (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
155 ev_job_render_class_init (EvJobRenderClass *class)
157 GObjectClass *oclass;
159 oclass = G_OBJECT_CLASS (class);
161 job_render_signals [PAGE_READY] =
162 g_signal_new ("page-ready",
165 G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
167 g_cclosure_marshal_VOID__VOID,
170 oclass->dispose = ev_job_render_dispose;
173 static void ev_job_thumbnail_init (EvJobThumbnail *job) { /* Do Nothing */ }
176 ev_job_thumbnail_dispose (GObject *object)
180 job = EV_JOB_THUMBNAIL (object);
182 if (job->thumbnail) {
183 g_object_unref (job->thumbnail);
184 job->thumbnail = NULL;
188 g_object_unref (job->rc);
192 (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
196 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
198 GObjectClass *oclass;
200 oclass = G_OBJECT_CLASS (class);
202 oclass->dispose = ev_job_thumbnail_dispose;
205 static void ev_job_print_init (EvJobPrint *job) { /* Do Nothing */ }
208 ev_job_print_dispose (GObject *object)
212 job = EV_JOB_PRINT (object);
214 if (job->temp_file) {
215 g_unlink (job->temp_file);
216 g_free (job->temp_file);
217 job->temp_file = NULL;
221 g_error_free (job->error);
226 g_free (job->ranges);
231 (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
235 ev_job_print_class_init (EvJobPrintClass *class)
237 GObjectClass *oclass;
239 oclass = G_OBJECT_CLASS (class);
241 oclass->dispose = ev_job_print_dispose;
244 /* Public functions */
246 ev_job_finished (EvJob *job)
248 g_return_if_fail (EV_IS_JOB (job));
250 g_signal_emit (job, job_signals[FINISHED], 0);
254 ev_job_links_new (EvDocument *document)
258 job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
259 job->document = g_object_ref (document);
265 ev_job_links_run (EvJobLinks *job)
267 g_return_if_fail (EV_IS_JOB_LINKS (job));
269 ev_document_doc_mutex_lock ();
270 job->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (EV_JOB (job)->document));
271 EV_JOB (job)->finished = TRUE;
272 ev_document_doc_mutex_unlock ();
277 ev_job_render_new (EvDocument *document,
281 EvRectangle *selection_points,
282 EvSelectionStyle selection_style,
285 gboolean include_forms,
286 gboolean include_links,
287 gboolean include_images,
288 gboolean include_text,
289 gboolean include_selection)
293 g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL);
294 if (include_selection)
295 g_return_val_if_fail (selection_points != NULL, NULL);
297 job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
299 EV_JOB (job)->document = g_object_ref (document);
300 job->rc = g_object_ref (rc);
301 job->target_width = width;
302 job->target_height = height;
303 job->selection_style = selection_style;
306 job->include_forms = include_forms;
307 job->include_links = include_links;
308 job->include_images = include_images;
309 job->include_text = include_text;
310 job->include_selection = include_selection;
312 if (include_selection)
313 job->selection_points = *selection_points;
315 if (EV_IS_ASYNC_RENDERER (document)) {
316 EV_JOB (job)->async = TRUE;
323 render_finished_cb (EvDocument *document,
327 g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
328 render_finished_cb, job);
330 /* FIXME: ps backend should be ported to cairo */
331 job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
332 job->page_ready = TRUE;
333 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
334 EV_JOB (job)->finished = TRUE;
335 ev_job_finished (EV_JOB (job));
339 notify_page_ready (EvJobRender *job)
341 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
347 ev_job_render_page_ready (EvJobRender *job)
349 job->page_ready = TRUE;
350 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
351 (GSourceFunc)notify_page_ready,
353 (GDestroyNotify)g_object_unref);
357 ev_job_render_run (EvJobRender *job)
359 g_return_if_fail (EV_IS_JOB_RENDER (job));
361 ev_document_doc_mutex_lock ();
363 if (EV_JOB (job)->async) {
364 EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document);
365 ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale,
367 g_signal_connect (EV_JOB (job)->document, "render_finished",
368 G_CALLBACK (render_finished_cb), job);
370 ev_document_fc_mutex_lock ();
372 job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
373 if (job->include_selection && EV_IS_SELECTION (EV_JOB (job)->document)) {
374 ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
377 &(job->selection_points),
379 job->selection_style,
380 &(job->text), &(job->base));
381 job->selection_region =
382 ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
384 job->selection_style,
385 &(job->selection_points));
388 ev_job_render_page_ready (job);
390 ev_document_fc_mutex_unlock ();
392 if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
394 ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document),
396 if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
398 ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
400 if (job->include_forms && EV_IS_DOCUMENT_FORMS (EV_JOB (job)->document))
401 job->form_field_mapping =
402 ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (EV_JOB(job)->document),
404 if (job->include_images && EV_IS_DOCUMENT_IMAGES (EV_JOB (job)->document))
406 ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (EV_JOB (job)->document),
408 EV_JOB (job)->finished = TRUE;
411 ev_document_doc_mutex_unlock ();
415 ev_job_thumbnail_new (EvDocument *document,
420 job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
422 EV_JOB (job)->document = g_object_ref (document);
423 job->rc = g_object_ref (rc);
429 ev_job_thumbnail_run (EvJobThumbnail *job)
431 g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
433 ev_document_doc_mutex_lock ();
436 ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
438 EV_JOB (job)->finished = TRUE;
440 ev_document_doc_mutex_unlock ();
443 static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
445 static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
448 ev_job_fonts_new (EvDocument *document)
452 job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
454 EV_JOB (job)->document = g_object_ref (document);
460 ev_job_fonts_run (EvJobFonts *job)
462 EvDocumentFonts *fonts;
464 g_return_if_fail (EV_IS_JOB_FONTS (job));
466 ev_document_doc_mutex_lock ();
468 fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
469 ev_document_fc_mutex_lock ();
470 job->scan_completed = !ev_document_fonts_scan (fonts, 20);
471 ev_document_fc_mutex_unlock ();
473 EV_JOB (job)->finished = TRUE;
475 ev_document_doc_mutex_unlock ();
478 static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ }
481 ev_job_load_dispose (GObject *object)
483 EvJobLoad *job = EV_JOB_LOAD (object);
491 g_error_free (job->error);
496 g_object_unref (job->dest);
500 if (job->search_string) {
501 g_free (job->search_string);
502 job->search_string = NULL;
505 (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
509 ev_job_load_class_init (EvJobLoadClass *class)
511 GObjectClass *oclass;
513 oclass = G_OBJECT_CLASS (class);
515 oclass->dispose = ev_job_load_dispose;
520 ev_job_load_new (const gchar *uri,
522 EvWindowRunMode mode,
523 const gchar *search_string)
527 job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
529 job->uri = g_strdup (uri);
531 job->dest = g_object_ref (dest);
535 job->search_string = g_strdup (search_string);
541 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
545 job->uri = g_strdup (uri);
549 ev_job_load_run (EvJobLoad *job)
551 g_return_if_fail (EV_IS_JOB_LOAD (job));
554 g_error_free (job->error);
558 ev_document_fc_mutex_lock ();
560 /* This job may already have a document even if the job didn't complete
561 because, e.g., a password is required - if so, just reload rather than
562 creating a new instance */
563 if (EV_JOB (job)->document) {
564 ev_document_load (EV_JOB (job)->document,
568 EV_JOB(job)->document =
569 ev_document_factory_get_document (job->uri,
573 ev_document_fc_mutex_unlock ();
574 EV_JOB (job)->finished = TRUE;
577 static void ev_job_save_init (EvJobSave *job) { /* Do Nothing */ }
580 ev_job_save_dispose (GObject *object)
582 EvJobSave *job = EV_JOB_SAVE (object);
589 if (job->document_uri) {
590 g_free (job->document_uri);
591 job->document_uri = NULL;
595 g_error_free (job->error);
599 (* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
603 ev_job_save_class_init (EvJobSaveClass *class)
605 GObjectClass *oclass;
607 oclass = G_OBJECT_CLASS (class);
609 oclass->dispose = ev_job_save_dispose;
613 ev_job_save_new (EvDocument *document,
615 const gchar *document_uri)
619 job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
621 EV_JOB (job)->document = g_object_ref (document);
622 job->uri = g_strdup (uri);
623 job->document_uri = g_strdup (document_uri);
630 ev_job_save_run (EvJobSave *job)
637 filename = ev_tmp_filename ("saveacopy");
638 tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
641 fd = g_mkstemp (tmp_filename);
644 gint save_errno = errno;
646 display_name = g_filename_display_name (tmp_filename);
647 g_set_error (&(job->error),
649 g_file_error_from_errno (save_errno),
650 _("Failed to create file “%s”: %s"),
651 display_name, g_strerror (save_errno));
652 g_free (display_name);
653 g_free (tmp_filename);
658 ev_document_doc_mutex_lock ();
660 /* Save document to temp filename */
661 local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
662 ev_document_save (EV_JOB (job)->document, local_uri, &(job->error));
665 ev_document_doc_mutex_unlock ();
672 /* If original document was compressed,
673 * compress it again before saving
675 if (g_object_get_data (G_OBJECT (EV_JOB (job)->document),
676 "uri-uncompressed")) {
677 EvCompressionType ctype = EV_COMPRESSION_NONE;
681 ext = g_strrstr (job->document_uri, ".gz");
682 if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
683 ctype = EV_COMPRESSION_GZIP;
685 ext = g_strrstr (job->document_uri, ".bz2");
686 if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
687 ctype = EV_COMPRESSION_BZIP2;
689 uri_comp = ev_file_compress (local_uri, ctype, &(job->error));
691 ev_tmp_filename_unlink (tmp_filename);
693 if (!uri_comp || job->error) {
696 local_uri = uri_comp;
700 g_free (tmp_filename);
710 ev_xfer_uri_simple (local_uri, job->uri, &(job->error));
711 ev_tmp_uri_unlink (local_uri);
715 ev_job_print_new (EvDocument *document,
719 EvPrintRange *ranges,
721 EvPrintPageSet page_set,
722 gint pages_per_sheet,
729 job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
731 EV_JOB (job)->document = g_object_ref (document);
733 job->format = format;
735 job->temp_file = NULL;
739 job->height = height;
741 job->ranges = ranges;
742 job->n_ranges = n_ranges;
744 job->page_set = page_set;
746 job->pages_per_sheet = CLAMP (pages_per_sheet, 1, 16);
748 job->copies = copies;
749 job->collate = collate;
750 job->reverse = reverse;
756 ev_print_job_get_first_page (EvJobPrint *job)
759 gint first_page = G_MAXINT;
761 if (job->n_ranges == 0)
764 for (i = 0; i < job->n_ranges; i++) {
765 if (job->ranges[i].start < first_page)
766 first_page = job->ranges[i].start;
769 return MAX (0, first_page);
773 ev_print_job_get_last_page (EvJobPrint *job)
776 gint last_page = G_MININT;
779 max_page = ev_document_get_n_pages (EV_JOB (job)->document) - 1;
781 if (job->n_ranges == 0)
784 for (i = 0; i < job->n_ranges; i++) {
785 if (job->ranges[i].end > last_page)
786 last_page = job->ranges[i].end;
789 return MIN (max_page, last_page);
793 ev_print_job_print_page_in_set (EvJobPrint *job,
796 switch (job->page_set) {
797 case EV_PRINT_PAGE_SET_EVEN:
798 return page % 2 == 0;
799 case EV_PRINT_PAGE_SET_ODD:
800 return page % 2 != 0;
801 case EV_PRINT_PAGE_SET_ALL:
809 ev_job_print_get_page_list (EvJobPrint *job,
812 gint i, j, page, max_page;
816 max_page = ev_document_get_n_pages (EV_JOB (job)->document) - 1;
818 for (i = 0; i < job->n_ranges; i++) {
822 if (job->ranges[i].start > max_page)
825 start = job->ranges[i].start + 1;
826 end = job->ranges[i].end <= max_page ? job->ranges[i].end + 1 : max_page + 1;
827 rsize = end - start + 1;
829 switch (job->page_set) {
830 case EV_PRINT_PAGE_SET_EVEN:
831 pages += start % 2 == 0 ? (rsize / 2) + (rsize % 2) : (rsize / 2);
833 case EV_PRINT_PAGE_SET_ODD:
834 pages += start % 2 != 0 ? (rsize / 2) + (rsize % 2) : (rsize / 2);
847 page_list = g_new (gint, pages);
850 for (i = 0; i < job->n_ranges; i++) {
851 for (j = job->ranges[i].start; j <= job->ranges[i].end; j++) {
855 if (ev_print_job_print_page_in_set (job, j + 1))
856 page_list[page++] = j;
864 ev_job_print_run (EvJobPrint *job)
866 EvDocument *document = EV_JOB (job)->document;
867 EvFileExporterContext fc;
877 g_return_if_fail (EV_IS_JOB_PRINT (job));
880 g_free (job->temp_file);
881 job->temp_file = NULL;
884 g_error_free (job->error);
887 filename = g_strdup_printf ("evince_print.%s.XXXXXX", job->format);
888 fd = g_file_open_tmp (filename, &job->temp_file, &job->error);
891 EV_JOB (job)->finished = TRUE;
895 page_list = ev_job_print_get_page_list (job, &n_pages);
898 EV_JOB (job)->finished = TRUE;
902 first_page = ev_print_job_get_first_page (job);
903 last_page = ev_print_job_get_last_page (job);
905 fc.format = g_ascii_strcasecmp (job->format, "pdf") == 0 ?
906 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
907 fc.filename = job->temp_file;
908 fc.first_page = MIN (first_page, last_page);
909 fc.last_page = MAX (first_page, last_page);
910 fc.paper_width = job->width;
911 fc.paper_height = job->height;
913 fc.pages_per_sheet = MAX (1, job->pages_per_sheet);
915 rc = ev_render_context_new (0, 0, 1.0);
917 ev_document_doc_mutex_lock ();
918 ev_file_exporter_begin (EV_FILE_EXPORTER (document), &fc);
920 for (i = 0; i < job->copies; i++) {
924 step = job->reverse ? -1 * job->pages_per_sheet : job->pages_per_sheet;
925 page = job->reverse ? (n_pages / job->pages_per_sheet) * job->pages_per_sheet : 0;
926 n_copies = job->collate ? job->copies : 1;
928 while ((job->reverse && (page >= 0)) || (!job->reverse && (page < n_pages))) {
931 ev_file_exporter_begin_page (EV_FILE_EXPORTER (document));
933 for (j = 0; j < job->pages_per_sheet; j++) {
936 if (p < 0 || p >= n_pages)
939 ev_render_context_set_page (rc, page_list[p]);
941 for (k = 0; k < n_copies; k++) {
942 ev_file_exporter_do_page (EV_FILE_EXPORTER (document), rc);
946 ev_file_exporter_end_page (EV_FILE_EXPORTER (document));
955 ev_file_exporter_end (EV_FILE_EXPORTER (document));
956 ev_document_doc_mutex_unlock ();
962 EV_JOB (job)->finished = TRUE;