2 #include "ev-job-queue.h"
3 #include "ev-document-thumbnails.h"
4 #include "ev-document-links.h"
5 #include "ev-document-images.h"
6 #include "ev-document-forms.h"
7 #include "ev-file-exporter.h"
8 #include "ev-document-factory.h"
9 #include "ev-document-misc.h"
10 #include "ev-file-helpers.h"
11 #include "ev-document-fonts.h"
12 #include "ev-async-renderer.h"
14 #include <glib/gstdio.h>
16 #include <libgnomevfs/gnome-vfs-uri.h>
17 #include <libgnomevfs/gnome-vfs-utils.h>
18 #include <libgnomevfs/gnome-vfs-ops.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_print_init (EvJobPrint *job);
31 static void ev_job_print_class_init (EvJobPrintClass *class);
43 static guint job_signals[LAST_SIGNAL] = { 0 };
44 static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
46 G_DEFINE_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
47 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
48 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
49 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
50 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
51 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
52 G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
54 static void ev_job_init (EvJob *job) { /* Do Nothing */ }
57 ev_job_dispose (GObject *object)
61 job = EV_JOB (object);
64 g_object_unref (job->document);
68 (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
72 ev_job_class_init (EvJobClass *class)
76 oclass = G_OBJECT_CLASS (class);
78 oclass->dispose = ev_job_dispose;
80 job_signals [FINISHED] =
81 g_signal_new ("finished",
84 G_STRUCT_OFFSET (EvJobClass, finished),
86 g_cclosure_marshal_VOID__VOID,
91 static void ev_job_links_init (EvJobLinks *job) { /* Do Nothing */ }
94 ev_job_links_dispose (GObject *object)
98 job = EV_JOB_LINKS (object);
101 g_object_unref (job->model);
105 (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
109 ev_job_links_class_init (EvJobLinksClass *class)
111 GObjectClass *oclass;
113 oclass = G_OBJECT_CLASS (class);
115 oclass->dispose = ev_job_links_dispose;
119 static void ev_job_render_init (EvJobRender *job) { /* Do Nothing */ }
122 ev_job_render_dispose (GObject *object)
126 job = EV_JOB_RENDER (object);
129 cairo_surface_destroy (job->surface);
134 g_object_unref (job->rc);
138 if (job->selection) {
139 cairo_surface_destroy (job->selection);
140 job->selection = NULL;
143 if (job->selection_region) {
144 gdk_region_destroy (job->selection_region);
145 job->selection_region = NULL;
148 (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
152 ev_job_render_class_init (EvJobRenderClass *class)
154 GObjectClass *oclass;
156 oclass = G_OBJECT_CLASS (class);
158 job_render_signals [PAGE_READY] =
159 g_signal_new ("page-ready",
162 G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
164 g_cclosure_marshal_VOID__VOID,
167 oclass->dispose = ev_job_render_dispose;
170 static void ev_job_thumbnail_init (EvJobThumbnail *job) { /* Do Nothing */ }
173 ev_job_thumbnail_dispose (GObject *object)
177 job = EV_JOB_THUMBNAIL (object);
179 if (job->thumbnail) {
180 g_object_unref (job->thumbnail);
181 job->thumbnail = NULL;
185 g_object_unref (job->rc);
189 (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
193 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
195 GObjectClass *oclass;
197 oclass = G_OBJECT_CLASS (class);
199 oclass->dispose = ev_job_thumbnail_dispose;
202 static void ev_job_print_init (EvJobPrint *job) { /* Do Nothing */ }
205 ev_job_print_dispose (GObject *object)
209 job = EV_JOB_PRINT (object);
211 if (job->temp_file) {
212 g_unlink (job->temp_file);
213 g_free (job->temp_file);
214 job->temp_file = NULL;
218 g_error_free (job->error);
223 g_free (job->ranges);
228 (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
232 ev_job_print_class_init (EvJobPrintClass *class)
234 GObjectClass *oclass;
236 oclass = G_OBJECT_CLASS (class);
238 oclass->dispose = ev_job_print_dispose;
241 /* Public functions */
243 ev_job_finished (EvJob *job)
245 g_return_if_fail (EV_IS_JOB (job));
247 g_signal_emit (job, job_signals[FINISHED], 0);
251 ev_job_links_new (EvDocument *document)
255 job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
256 job->document = g_object_ref (document);
262 ev_job_links_run (EvJobLinks *job)
264 g_return_if_fail (EV_IS_JOB_LINKS (job));
266 ev_document_doc_mutex_lock ();
267 job->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (EV_JOB (job)->document));
268 EV_JOB (job)->finished = TRUE;
269 ev_document_doc_mutex_unlock ();
274 ev_job_render_new (EvDocument *document,
278 EvRectangle *selection_points,
279 EvSelectionStyle selection_style,
282 gboolean include_forms,
283 gboolean include_links,
284 gboolean include_images,
285 gboolean include_text,
286 gboolean include_selection)
290 g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL);
291 if (include_selection)
292 g_return_val_if_fail (selection_points != NULL, NULL);
294 job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
296 EV_JOB (job)->document = g_object_ref (document);
297 job->rc = g_object_ref (rc);
298 job->target_width = width;
299 job->target_height = height;
300 job->selection_style = selection_style;
303 job->include_forms = include_forms;
304 job->include_links = include_links;
305 job->include_images = include_images;
306 job->include_text = include_text;
307 job->include_selection = include_selection;
309 if (include_selection)
310 job->selection_points = *selection_points;
312 if (EV_IS_ASYNC_RENDERER (document)) {
313 EV_JOB (job)->async = TRUE;
320 render_finished_cb (EvDocument *document,
324 g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
325 render_finished_cb, job);
327 /* FIXME: ps backend should be ported to cairo */
328 job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
329 job->page_ready = TRUE;
330 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
331 EV_JOB (job)->finished = TRUE;
332 ev_job_finished (EV_JOB (job));
336 notify_page_ready (EvJobRender *job)
338 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
344 ev_job_render_page_ready (EvJobRender *job)
346 job->page_ready = TRUE;
347 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
348 (GSourceFunc)notify_page_ready,
350 (GDestroyNotify)g_object_unref);
354 ev_job_render_run (EvJobRender *job)
356 g_return_if_fail (EV_IS_JOB_RENDER (job));
358 ev_document_doc_mutex_lock ();
360 if (EV_JOB (job)->async) {
361 EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document);
362 ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale,
364 g_signal_connect (EV_JOB (job)->document, "render_finished",
365 G_CALLBACK (render_finished_cb), job);
367 ev_document_fc_mutex_lock ();
369 job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
370 if (job->include_selection && EV_IS_SELECTION (EV_JOB (job)->document)) {
371 ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
374 &(job->selection_points),
376 job->selection_style,
377 &(job->text), &(job->base));
378 job->selection_region =
379 ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
381 job->selection_style,
382 &(job->selection_points));
385 ev_job_render_page_ready (job);
387 ev_document_fc_mutex_unlock ();
389 if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
391 ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document),
393 if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
395 ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
397 if (job->include_forms && EV_IS_DOCUMENT_FORMS (EV_JOB (job)->document))
398 job->form_field_mapping =
399 ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (EV_JOB(job)->document),
401 if (job->include_images && EV_IS_DOCUMENT_IMAGES (EV_JOB (job)->document))
403 ev_document_images_get_images (EV_DOCUMENT_IMAGES (EV_JOB (job)->document),
405 EV_JOB (job)->finished = TRUE;
408 ev_document_doc_mutex_unlock ();
412 ev_job_thumbnail_new (EvDocument *document,
417 job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
419 EV_JOB (job)->document = g_object_ref (document);
420 job->rc = g_object_ref (rc);
426 ev_job_thumbnail_run (EvJobThumbnail *job)
428 g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
430 ev_document_doc_mutex_lock ();
433 ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
435 EV_JOB (job)->finished = TRUE;
437 ev_document_doc_mutex_unlock ();
440 static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
442 static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
445 ev_job_fonts_new (EvDocument *document)
449 job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
451 EV_JOB (job)->document = g_object_ref (document);
457 ev_job_fonts_run (EvJobFonts *job)
459 EvDocumentFonts *fonts;
461 g_return_if_fail (EV_IS_JOB_FONTS (job));
463 ev_document_doc_mutex_lock ();
465 fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
466 ev_document_fc_mutex_lock ();
467 job->scan_completed = !ev_document_fonts_scan (fonts, 20);
468 ev_document_fc_mutex_unlock ();
470 EV_JOB (job)->finished = TRUE;
472 ev_document_doc_mutex_unlock ();
475 static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ }
478 ev_job_load_dispose (GObject *object)
480 EvJobLoad *job = EV_JOB_LOAD (object);
488 g_error_free (job->error);
493 g_object_unref (job->dest);
497 (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
501 ev_job_load_class_init (EvJobLoadClass *class)
503 GObjectClass *oclass;
505 oclass = G_OBJECT_CLASS (class);
507 oclass->dispose = ev_job_load_dispose;
512 ev_job_load_new (const gchar *uri, EvLinkDest *dest, EvWindowRunMode mode)
516 job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
518 job->uri = g_strdup (uri);
520 job->dest = g_object_ref (dest);
528 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
532 job->uri = g_strdup (uri);
536 ev_job_load_run (EvJobLoad *job)
538 g_return_if_fail (EV_IS_JOB_LOAD (job));
541 g_error_free (job->error);
545 ev_document_fc_mutex_lock ();
547 /* This job may already have a document even if the job didn't complete
548 because, e.g., a password is required - if so, just reload rather than
549 creating a new instance */
550 if (EV_JOB (job)->document) {
551 ev_document_load (EV_JOB (job)->document,
555 EV_JOB(job)->document =
556 ev_document_factory_get_document (job->uri,
560 ev_document_fc_mutex_unlock ();
561 EV_JOB (job)->finished = TRUE;
565 ev_job_print_new (EvDocument *document,
569 EvPrintRange *ranges,
571 EvPrintPageSet page_set,
572 gint pages_per_sheet,
579 job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
581 EV_JOB (job)->document = g_object_ref (document);
583 job->format = format;
585 job->temp_file = NULL;
589 job->height = height;
591 job->ranges = ranges;
592 job->n_ranges = n_ranges;
594 job->page_set = page_set;
596 job->pages_per_sheet = pages_per_sheet;
598 job->copies = copies;
599 job->collate = collate;
600 job->reverse = reverse;
606 ev_print_job_get_first_page (EvJobPrint *job)
609 gint first_page = G_MAXINT;
611 if (job->n_ranges == 0)
614 for (i = 0; i < job->n_ranges; i++) {
615 if (job->ranges[i].start < first_page)
616 first_page = job->ranges[i].start;
619 return MAX (0, first_page);
623 ev_print_job_get_last_page (EvJobPrint *job)
626 gint last_page = G_MININT;
629 max_page = ev_document_get_n_pages (EV_JOB (job)->document) - 1;
631 if (job->n_ranges == 0)
634 for (i = 0; i < job->n_ranges; i++) {
635 if (job->ranges[i].end > last_page)
636 last_page = job->ranges[i].end;
639 return MIN (max_page, last_page);
643 ev_print_job_print_page_in_range (EvJobPrint *job,
648 for (i = 0; i < job->n_ranges; i++) {
649 if (page >= job->ranges[i].start &&
650 page <= job->ranges[i].end)
658 ev_print_job_print_page_in_set (EvJobPrint *job,
661 switch (job->page_set) {
662 case EV_PRINT_PAGE_SET_EVEN:
663 return page % 2 == 0;
664 case EV_PRINT_PAGE_SET_ODD:
665 return page % 2 != 0;
666 case EV_PRINT_PAGE_SET_ALL:
674 ev_job_print_do_page (EvJobPrint *job, gint page)
676 EvDocument *document = EV_JOB (job)->document;
679 rc = ev_render_context_new (0, page, 1.0);
680 ev_file_exporter_do_page (EV_FILE_EXPORTER (document), rc);
685 ev_job_print_run (EvJobPrint *job)
687 EvDocument *document = EV_JOB (job)->document;
688 EvFileExporterContext fc;
695 g_return_if_fail (EV_IS_JOB_PRINT (job));
698 g_free (job->temp_file);
699 job->temp_file = NULL;
702 g_error_free (job->error);
705 filename = g_strdup_printf ("evince_print.%s.XXXXXX", job->format);
706 fd = g_file_open_tmp (filename, &job->temp_file, &job->error);
709 EV_JOB (job)->finished = TRUE;
713 first_page = ev_print_job_get_first_page (job);
714 last_page = ev_print_job_get_last_page (job);
716 fc.format = g_ascii_strcasecmp (job->format, "pdf") == 0 ?
717 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
718 fc.filename = job->temp_file;
719 fc.first_page = MIN (first_page, last_page);
720 fc.last_page = MAX (first_page, last_page);
721 fc.paper_width = job->width;
722 fc.paper_height = job->height;
724 fc.pages_per_sheet = MAX (1, job->pages_per_sheet);
726 ev_document_doc_mutex_lock ();
727 ev_file_exporter_begin (EV_FILE_EXPORTER (document), &fc);
728 ev_document_doc_mutex_unlock ();
730 for (i = 0; i < job->copies; i++) {
733 step = job->reverse ? -1 : 1;
734 page = job->reverse ? last_page : first_page;
736 while ((job->reverse && (page >= first_page)) ||
737 (!job->reverse && (page <= last_page))) {
741 if (job->n_ranges > 0 &&
742 !ev_print_job_print_page_in_range (job, page)) {
747 if (!ev_print_job_print_page_in_set (job, page + 1)) {
753 n_pages = job->copies;
755 for (j = 0; j < n_pages; j++) {
756 ev_document_doc_mutex_lock ();
757 ev_job_print_do_page (job, page);
758 ev_document_doc_mutex_unlock ();
768 ev_document_doc_mutex_lock ();
769 ev_file_exporter_end (EV_FILE_EXPORTER (document));
770 ev_document_doc_mutex_unlock ();
774 EV_JOB (job)->finished = TRUE;