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-document-factory.h"
8 #include "ev-document-misc.h"
9 #include "ev-file-helpers.h"
10 #include "ev-document-fonts.h"
11 #include "ev-selection.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,
281 gboolean include_forms,
282 gboolean include_links,
283 gboolean include_images,
284 gboolean include_text,
285 gboolean include_selection)
289 g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL);
290 if (include_selection)
291 g_return_val_if_fail (selection_points != NULL, NULL);
293 job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
295 EV_JOB (job)->document = g_object_ref (document);
296 job->rc = g_object_ref (rc);
297 job->target_width = width;
298 job->target_height = height;
301 job->include_forms = include_forms;
302 job->include_links = include_links;
303 job->include_images = include_images;
304 job->include_text = include_text;
305 job->include_selection = include_selection;
307 if (include_selection)
308 job->selection_points = *selection_points;
310 if (EV_IS_ASYNC_RENDERER (document)) {
311 EV_JOB (job)->async = TRUE;
318 render_finished_cb (EvDocument *document,
322 g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
323 render_finished_cb, job);
325 /* FIXME: ps backend should be ported to cairo */
326 job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
327 job->page_ready = TRUE;
328 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
329 EV_JOB (job)->finished = TRUE;
330 ev_job_finished (EV_JOB (job));
334 notify_page_ready (EvJobRender *job)
336 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
342 ev_job_render_page_ready (EvJobRender *job)
344 job->page_ready = TRUE;
345 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
346 (GSourceFunc)notify_page_ready,
348 (GDestroyNotify)g_object_unref);
352 ev_job_render_run (EvJobRender *job)
354 g_return_if_fail (EV_IS_JOB_RENDER (job));
356 ev_document_doc_mutex_lock ();
358 if (EV_JOB (job)->async) {
359 EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document);
360 ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale,
362 g_signal_connect (EV_JOB (job)->document, "render_finished",
363 G_CALLBACK (render_finished_cb), job);
365 ev_document_fc_mutex_lock ();
367 job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
368 if (job->include_selection && EV_IS_SELECTION (EV_JOB (job)->document)) {
369 ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
372 &(job->selection_points),
374 &(job->text), &(job->base));
375 job->selection_region =
376 ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
378 &(job->selection_points));
381 ev_job_render_page_ready (job);
383 ev_document_fc_mutex_unlock ();
385 if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
387 ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document),
389 if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
391 ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
393 if (job->include_forms && EV_IS_DOCUMENT_FORMS (EV_JOB (job)->document))
394 job->form_field_mapping =
395 ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (EV_JOB(job)->document),
397 if (job->include_images && EV_IS_DOCUMENT_IMAGES (EV_JOB (job)->document))
399 ev_document_images_get_images (EV_DOCUMENT_IMAGES (EV_JOB (job)->document),
401 EV_JOB (job)->finished = TRUE;
404 ev_document_doc_mutex_unlock ();
408 ev_job_thumbnail_new (EvDocument *document,
413 job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
415 EV_JOB (job)->document = g_object_ref (document);
416 job->rc = g_object_ref (rc);
422 ev_job_thumbnail_run (EvJobThumbnail *job)
424 g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
426 ev_document_doc_mutex_lock ();
429 ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
431 EV_JOB (job)->finished = TRUE;
433 ev_document_doc_mutex_unlock ();
436 static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
438 static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
441 ev_job_fonts_new (EvDocument *document)
445 job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
447 EV_JOB (job)->document = g_object_ref (document);
453 ev_job_fonts_run (EvJobFonts *job)
455 EvDocumentFonts *fonts;
457 g_return_if_fail (EV_IS_JOB_FONTS (job));
459 ev_document_doc_mutex_lock ();
461 fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
462 ev_document_fc_mutex_lock ();
463 job->scan_completed = !ev_document_fonts_scan (fonts, 20);
464 ev_document_fc_mutex_unlock ();
466 EV_JOB (job)->finished = TRUE;
468 ev_document_doc_mutex_unlock ();
471 static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ }
474 ev_job_load_dispose (GObject *object)
476 EvJobLoad *job = EV_JOB_LOAD (object);
484 g_error_free (job->error);
489 g_object_unref (job->dest);
493 (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
497 ev_job_load_class_init (EvJobLoadClass *class)
499 GObjectClass *oclass;
501 oclass = G_OBJECT_CLASS (class);
503 oclass->dispose = ev_job_load_dispose;
508 ev_job_load_new (const gchar *uri, EvLinkDest *dest, EvWindowRunMode mode)
512 job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
514 job->uri = g_strdup (uri);
516 job->dest = g_object_ref (dest);
524 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
528 job->uri = g_strdup (uri);
532 ev_job_load_run (EvJobLoad *job)
534 g_return_if_fail (EV_IS_JOB_LOAD (job));
537 g_error_free (job->error);
541 ev_document_fc_mutex_lock ();
543 /* This job may already have a document even if the job didn't complete
544 because, e.g., a password is required - if so, just reload rather than
545 creating a new instance */
546 if (EV_JOB (job)->document) {
547 ev_document_load (EV_JOB (job)->document,
551 EV_JOB(job)->document =
552 ev_document_factory_get_document (job->uri,
556 ev_document_fc_mutex_unlock ();
557 EV_JOB (job)->finished = TRUE;
561 ev_job_print_new (EvDocument *document,
565 EvFileExporterOrientation orientation,
566 EvPrintRange *ranges,
568 EvPrintPageSet page_set,
569 gint pages_per_sheet,
576 job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
578 EV_JOB (job)->document = g_object_ref (document);
580 job->format = format;
582 job->temp_file = NULL;
586 job->height = height;
587 job->orientation = orientation;
589 job->ranges = ranges;
590 job->n_ranges = n_ranges;
592 job->page_set = page_set;
594 job->pages_per_sheet = pages_per_sheet;
596 job->copies = copies;
597 job->collate = collate;
598 job->reverse = reverse;
604 ev_print_job_get_first_page (EvJobPrint *job)
607 gint first_page = G_MAXINT;
609 if (job->n_ranges == 0)
612 for (i = 0; i < job->n_ranges; i++) {
613 if (job->ranges[i].start < first_page)
614 first_page = job->ranges[i].start;
617 return MAX (0, first_page);
621 ev_print_job_get_last_page (EvJobPrint *job)
624 gint last_page = G_MININT;
627 max_page = ev_document_get_n_pages (EV_JOB (job)->document) - 1;
629 if (job->n_ranges == 0)
632 for (i = 0; i < job->n_ranges; i++) {
633 if (job->ranges[i].end > last_page)
634 last_page = job->ranges[i].end;
637 return MIN (max_page, last_page);
641 ev_print_job_print_page_in_range (EvJobPrint *job,
646 for (i = 0; i < job->n_ranges; i++) {
647 if (page >= job->ranges[i].start &&
648 page <= job->ranges[i].end)
656 ev_print_job_print_page_in_set (EvJobPrint *job,
659 switch (job->page_set) {
660 case EV_PRINT_PAGE_SET_EVEN:
661 return page % 2 == 0;
662 case EV_PRINT_PAGE_SET_ODD:
663 return page % 2 != 0;
664 case EV_PRINT_PAGE_SET_ALL:
672 ev_job_print_do_page (EvJobPrint *job, gint page)
674 EvDocument *document = EV_JOB (job)->document;
677 rc = ev_render_context_new (0, page, 1.0);
678 ev_file_exporter_do_page (EV_FILE_EXPORTER (document), rc);
683 ev_job_print_run (EvJobPrint *job)
685 EvDocument *document = EV_JOB (job)->document;
686 EvFileExporterContext fc;
693 g_return_if_fail (EV_IS_JOB_PRINT (job));
696 g_free (job->temp_file);
697 job->temp_file = NULL;
700 g_error_free (job->error);
703 filename = g_strdup_printf ("evince_print.%s.XXXXXX", job->format);
704 fd = g_file_open_tmp (filename, &job->temp_file, &job->error);
707 EV_JOB (job)->finished = TRUE;
711 first_page = ev_print_job_get_first_page (job);
712 last_page = ev_print_job_get_last_page (job);
714 fc.format = g_ascii_strcasecmp (job->format, "pdf") == 0 ?
715 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
716 fc.filename = job->temp_file;
717 fc.first_page = MIN (first_page, last_page);
718 fc.last_page = MAX (first_page, last_page);
719 fc.paper_width = job->width;
720 fc.paper_height = job->height;
721 fc.orientation = job->orientation;
723 fc.pages_per_sheet = MAX (1, job->pages_per_sheet);
725 ev_document_doc_mutex_lock ();
726 ev_file_exporter_begin (EV_FILE_EXPORTER (document), &fc);
727 ev_document_doc_mutex_unlock ();
729 for (i = 0; i < job->copies; i++) {
732 step = job->reverse ? -1 : 1;
733 page = job->reverse ? last_page : first_page;
735 while ((job->reverse && (page >= first_page)) ||
736 (!job->reverse && (page <= last_page))) {
740 if (job->n_ranges > 0 &&
741 !ev_print_job_print_page_in_range (job, page)) {
746 if (!ev_print_job_print_page_in_set (job, page + 1)) {
752 n_pages = job->copies;
754 for (j = 0; j < n_pages; j++) {
755 ev_document_doc_mutex_lock ();
756 ev_job_print_do_page (job, page);
757 ev_document_doc_mutex_unlock ();
767 ev_document_doc_mutex_lock ();
768 ev_file_exporter_end (EV_FILE_EXPORTER (document));
769 ev_document_doc_mutex_unlock ();
773 EV_JOB (job)->finished = TRUE;