]> www.fi.muni.cz Git - evince.git/blob - libview/ev-jobs.c
df15f6db865ce0fa489905019abf982b38190b43
[evince.git] / libview / ev-jobs.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
4  *  Copyright (C) 2005 Red Hat, Inc
5  *
6  * Evince is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Evince is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include "ev-jobs.h"
24 #include "ev-document-thumbnails.h"
25 #include "ev-document-links.h"
26 #include "ev-document-images.h"
27 #include "ev-document-forms.h"
28 #include "ev-file-exporter.h"
29 #include "ev-document-factory.h"
30 #include "ev-document-misc.h"
31 #include "ev-file-helpers.h"
32 #include "ev-document-fonts.h"
33 #include "ev-document-security.h"
34 #include "ev-document-find.h"
35 #include "ev-document-layers.h"
36 #include "ev-document-print.h"
37 #include "ev-document-annotations.h"
38 #include "ev-document-attachments.h"
39 #include "ev-debug.h"
40
41 #include <errno.h>
42 #include <glib/gstdio.h>
43 #include <glib/gi18n-lib.h>
44 #include <unistd.h>
45
46 static void ev_job_init                   (EvJob                 *job);
47 static void ev_job_class_init             (EvJobClass            *class);
48 static void ev_job_links_init             (EvJobLinks            *job);
49 static void ev_job_links_class_init       (EvJobLinksClass       *class);
50 static void ev_job_attachments_init       (EvJobAttachments      *job);
51 static void ev_job_attachments_class_init (EvJobAttachmentsClass *class);
52 static void ev_job_render_init            (EvJobRender           *job);
53 static void ev_job_render_class_init      (EvJobRenderClass      *class);
54 static void ev_job_page_data_init         (EvJobPageData         *job);
55 static void ev_job_page_data_class_init   (EvJobPageDataClass    *class);
56 static void ev_job_thumbnail_init         (EvJobThumbnail        *job);
57 static void ev_job_thumbnail_class_init   (EvJobThumbnailClass   *class);
58 static void ev_job_load_init              (EvJobLoad             *job);
59 static void ev_job_load_class_init        (EvJobLoadClass        *class);
60 static void ev_job_save_init              (EvJobSave             *job);
61 static void ev_job_save_class_init        (EvJobSaveClass        *class);
62 static void ev_job_find_init              (EvJobFind             *job);
63 static void ev_job_find_class_init        (EvJobFindClass        *class);
64 static void ev_job_layers_init            (EvJobLayers           *job);
65 static void ev_job_layers_class_init      (EvJobLayersClass      *class);
66 static void ev_job_export_init            (EvJobExport           *job);
67 static void ev_job_export_class_init      (EvJobExportClass      *class);
68 static void ev_job_print_init             (EvJobPrint            *job);
69 static void ev_job_print_class_init       (EvJobPrintClass       *class);
70
71 enum {
72         CANCELLED,
73         FINISHED,
74         LAST_SIGNAL
75 };
76
77 enum {
78         FONTS_UPDATED,
79         FONTS_LAST_SIGNAL
80 };
81
82 enum {
83         FIND_UPDATED,
84         FIND_LAST_SIGNAL
85 };
86
87 static guint job_signals[LAST_SIGNAL] = { 0 };
88 static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
89 static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
90
91 G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
92 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
93 G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, EV_TYPE_JOB)
94 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
95 G_DEFINE_TYPE (EvJobPageData, ev_job_page_data, EV_TYPE_JOB)
96 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
97 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
98 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
99 G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
100 G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
101 G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
102 G_DEFINE_TYPE (EvJobExport, ev_job_export, EV_TYPE_JOB)
103 G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
104
105 /* EvJob */
106 static void
107 ev_job_init (EvJob *job)
108 {
109         job->cancellable = g_cancellable_new ();
110 }
111
112 static void
113 ev_job_dispose (GObject *object)
114 {
115         EvJob *job;
116
117         job = EV_JOB (object);
118
119         if (job->document) {
120                 g_object_unref (job->document);
121                 job->document = NULL;
122         }
123
124         if (job->cancellable) {
125                 g_object_unref (job->cancellable);
126                 job->cancellable = NULL;
127         }
128
129         if (job->error) {
130                 g_error_free (job->error);
131                 job->error = NULL;
132         }
133
134         (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
135 }
136
137 static void
138 ev_job_class_init (EvJobClass *class)
139 {
140         GObjectClass *oclass;
141
142         oclass = G_OBJECT_CLASS (class);
143
144         oclass->dispose = ev_job_dispose;
145
146         job_signals[CANCELLED] =
147                 g_signal_new ("cancelled",
148                               EV_TYPE_JOB,
149                               G_SIGNAL_RUN_LAST,
150                               G_STRUCT_OFFSET (EvJobClass, cancelled),
151                               NULL, NULL,
152                               g_cclosure_marshal_VOID__VOID,
153                               G_TYPE_NONE, 0);
154         job_signals [FINISHED] =
155                 g_signal_new ("finished",
156                               EV_TYPE_JOB,
157                               G_SIGNAL_RUN_FIRST,
158                               G_STRUCT_OFFSET (EvJobClass, finished),
159                               NULL, NULL,
160                               g_cclosure_marshal_VOID__VOID,
161                               G_TYPE_NONE, 0);
162 }
163
164 static gboolean
165 emit_finished (EvJob *job)
166 {
167         ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
168
169         job->idle_finished_id = 0;
170         
171         if (job->cancelled) {
172                 ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit finished", EV_GET_TYPE_NAME (job), job);
173         } else {
174                 ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
175                 g_signal_emit (job, job_signals[FINISHED], 0);
176         }
177         
178         return FALSE;
179 }
180
181 static void
182 ev_job_emit_finished (EvJob *job)
183 {
184         ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
185
186         if (g_cancellable_is_cancelled (job->cancellable)) {
187                 ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, returning", EV_GET_TYPE_NAME (job), job);
188                 return;
189         }
190         
191         job->finished = TRUE;
192         
193         if (job->run_mode == EV_JOB_RUN_THREAD) {
194                 job->idle_finished_id =
195                         g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
196                                          (GSourceFunc)emit_finished,
197                                          g_object_ref (job),
198                                          (GDestroyNotify)g_object_unref);
199         } else {
200                 ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
201                 g_signal_emit (job, job_signals[FINISHED], 0);
202         }
203 }
204
205 gboolean
206 ev_job_run (EvJob *job)
207 {
208         EvJobClass *class = EV_JOB_GET_CLASS (job);
209         
210         return class->run (job);
211 }
212
213 void
214 ev_job_cancel (EvJob *job)
215 {
216         if (job->cancelled || (job->finished && job->idle_finished_id == 0))
217                 return;
218
219         ev_debug_message (DEBUG_JOBS, "job %s (%p) cancelled", EV_GET_TYPE_NAME (job), job);
220         ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
221         
222         /* This should never be called from a thread */
223         job->cancelled = TRUE;
224         g_cancellable_cancel (job->cancellable);
225         g_signal_emit (job, job_signals[CANCELLED], 0);
226 }
227
228 void
229 ev_job_failed (EvJob       *job,
230                GQuark       domain,
231                gint         code,
232                const gchar *format,
233                ...)
234 {
235         va_list args;
236         gchar  *message;
237         
238         if (job->failed || job->finished)
239                 return;
240
241         ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
242         
243         job->failed = TRUE;
244         
245         va_start (args, format);
246         message = g_strdup_vprintf (format, args);
247         va_end (args);
248         
249         job->error = g_error_new_literal (domain, code, message);
250         g_free (message);
251         
252         ev_job_emit_finished (job);                                                                                                               
253 }
254
255 void
256 ev_job_failed_from_error (EvJob  *job,
257                           GError *error)
258 {
259         if (job->failed || job->finished)
260                 return;
261         
262         ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
263
264         job->failed = TRUE;
265         job->error = g_error_copy (error);
266
267         ev_job_emit_finished (job);
268 }
269
270 void
271 ev_job_succeeded (EvJob *job)
272 {
273         if (job->finished)
274                 return;
275
276         ev_debug_message (DEBUG_JOBS, "job %s (%p) succeeded", EV_GET_TYPE_NAME (job), job);
277         
278         job->failed = FALSE;
279         ev_job_emit_finished (job);
280 }
281
282 gboolean
283 ev_job_is_finished (EvJob *job)
284 {
285         return job->finished;
286 }
287
288 gboolean
289 ev_job_is_failed (EvJob *job)
290 {
291         return job->failed;
292 }
293
294 EvJobRunMode
295 ev_job_get_run_mode (EvJob *job)
296 {
297         return job->run_mode;
298 }
299
300 void
301 ev_job_set_run_mode (EvJob       *job,
302                      EvJobRunMode run_mode)
303 {
304         job->run_mode = run_mode;
305 }
306
307 /* EvJobLinks */
308 static void
309 ev_job_links_init (EvJobLinks *job)
310 {
311         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
312 }
313
314 static void
315 ev_job_links_dispose (GObject *object)
316 {
317         EvJobLinks *job;
318
319         ev_debug_message (DEBUG_JOBS, NULL);
320         
321         job = EV_JOB_LINKS (object);
322
323         if (job->model) {
324                 g_object_unref (job->model);
325                 job->model = NULL;
326         }
327
328         (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
329 }
330
331 static gboolean
332 ev_job_links_run (EvJob *job)
333 {
334         EvJobLinks *job_links = EV_JOB_LINKS (job);
335
336         ev_debug_message (DEBUG_JOBS, NULL);
337         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
338         
339         ev_document_doc_mutex_lock ();
340         job_links->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (job->document));
341         ev_document_doc_mutex_unlock ();
342         
343         ev_job_succeeded (job);
344         
345         return FALSE;
346 }
347
348 static void
349 ev_job_links_class_init (EvJobLinksClass *class)
350 {
351         GObjectClass *oclass = G_OBJECT_CLASS (class);
352         EvJobClass   *job_class = EV_JOB_CLASS (class);
353
354         oclass->dispose = ev_job_links_dispose;
355         job_class->run = ev_job_links_run;
356 }
357
358 EvJob *
359 ev_job_links_new (EvDocument *document)
360 {
361         EvJob *job;
362
363         ev_debug_message (DEBUG_JOBS, NULL);
364
365         job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
366         job->document = g_object_ref (document);
367         
368         return job;
369 }
370
371 /* EvJobAttachments */
372 static void
373 ev_job_attachments_init (EvJobAttachments *job)
374 {
375         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
376 }
377
378 static void
379 ev_job_attachments_dispose (GObject *object)
380 {
381         EvJobAttachments *job;
382
383         ev_debug_message (DEBUG_JOBS, NULL);
384         
385         job = EV_JOB_ATTACHMENTS (object);
386
387         if (job->attachments) {
388                 g_list_foreach (job->attachments, (GFunc)g_object_unref, NULL);
389                 g_list_free (job->attachments);
390                 job->attachments = NULL;
391         }
392
393         (* G_OBJECT_CLASS (ev_job_attachments_parent_class)->dispose) (object);
394 }
395
396 static gboolean
397 ev_job_attachments_run (EvJob *job)
398 {
399         EvJobAttachments *job_attachments = EV_JOB_ATTACHMENTS (job);
400
401         ev_debug_message (DEBUG_JOBS, NULL);
402         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
403
404         ev_document_doc_mutex_lock ();
405         job_attachments->attachments =
406                 ev_document_attachments_get_attachments (EV_DOCUMENT_ATTACHMENTS (job->document));
407         ev_document_doc_mutex_unlock ();
408
409         ev_job_succeeded (job);
410
411         return FALSE;
412 }
413
414 static void
415 ev_job_attachments_class_init (EvJobAttachmentsClass *class)
416 {
417         GObjectClass *oclass = G_OBJECT_CLASS (class);
418         EvJobClass   *job_class = EV_JOB_CLASS (class);
419
420         oclass->dispose = ev_job_attachments_dispose;
421         job_class->run = ev_job_attachments_run;
422 }
423
424 EvJob *
425 ev_job_attachments_new (EvDocument *document)
426 {
427         EvJob *job;
428
429         ev_debug_message (DEBUG_JOBS, NULL);
430
431         job = g_object_new (EV_TYPE_JOB_ATTACHMENTS, NULL);
432         job->document = g_object_ref (document);
433         
434         return job;
435 }
436
437 /* EvJobRender */
438 static void
439 ev_job_render_init (EvJobRender *job)
440 {
441         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
442 }
443
444 static void
445 ev_job_render_dispose (GObject *object)
446 {
447         EvJobRender *job;
448
449         job = EV_JOB_RENDER (object);
450
451         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->page, job);
452
453         if (job->surface) {
454                 cairo_surface_destroy (job->surface);
455                 job->surface = NULL;
456         }
457
458         if (job->selection) {
459                 cairo_surface_destroy (job->selection);
460                 job->selection = NULL;
461         }
462
463         if (job->selection_region) {
464                 gdk_region_destroy (job->selection_region);
465                 job->selection_region = NULL;
466         }
467
468         (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
469 }
470
471 static gboolean
472 ev_job_render_run (EvJob *job)
473 {
474         EvJobRender     *job_render = EV_JOB_RENDER (job);
475         EvPage          *ev_page;
476         EvRenderContext *rc;
477
478         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
479         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
480         
481         ev_document_doc_mutex_lock ();
482
483         ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job_render->page);
484                 
485         ev_document_fc_mutex_lock ();
486
487         ev_page = ev_document_get_page (job->document, job_render->page);
488         rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
489         g_object_unref (ev_page);
490
491         job_render->surface = ev_document_render (job->document, rc);
492         /* If job was cancelled during the page rendering,
493          * we return now, so that the thread is finished ASAP
494          */
495         if (g_cancellable_is_cancelled (job->cancellable)) {
496                 ev_document_fc_mutex_unlock ();
497                 ev_document_doc_mutex_unlock ();
498                 g_object_unref (rc);
499
500                 return FALSE;
501         }
502
503         if (job_render->include_selection && EV_IS_SELECTION (job->document)) {
504                 ev_selection_render_selection (EV_SELECTION (job->document),
505                                                rc,
506                                                &(job_render->selection),
507                                                &(job_render->selection_points),
508                                                NULL,
509                                                job_render->selection_style,
510                                                &(job_render->text), &(job_render->base));
511                 job_render->selection_region =
512                         ev_selection_get_selection_region (EV_SELECTION (job->document),
513                                                            rc,
514                                                            job_render->selection_style,
515                                                            &(job_render->selection_points));
516         }
517
518         g_object_unref (rc);
519
520         ev_document_fc_mutex_unlock ();
521         ev_document_doc_mutex_unlock ();
522         
523         ev_job_succeeded (job);
524         
525         return FALSE;
526 }
527
528 static void
529 ev_job_render_class_init (EvJobRenderClass *class)
530 {
531         GObjectClass *oclass = G_OBJECT_CLASS (class);
532         EvJobClass   *job_class = EV_JOB_CLASS (class);
533
534         oclass->dispose = ev_job_render_dispose;
535         job_class->run = ev_job_render_run;
536 }
537
538 EvJob *
539 ev_job_render_new (EvDocument   *document,
540                    gint          page,
541                    gint          rotation,
542                    gdouble       scale,
543                    gint          width,
544                    gint          height)
545 {
546         EvJobRender *job;
547
548         ev_debug_message (DEBUG_JOBS, "page: %d", page);
549         
550         job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
551
552         EV_JOB (job)->document = g_object_ref (document);
553         job->page = page;
554         job->rotation = rotation;
555         job->scale = scale;
556         job->target_width = width;
557         job->target_height = height;
558
559         return EV_JOB (job);
560 }
561
562 void
563 ev_job_render_set_selection_info (EvJobRender     *job,
564                                   EvRectangle     *selection_points,
565                                   EvSelectionStyle selection_style,
566                                   GdkColor        *text,
567                                   GdkColor        *base)
568 {
569         job->include_selection = TRUE;
570
571         job->selection_points = *selection_points;
572         job->selection_style = selection_style;
573         job->text = *text;
574         job->base = *base;
575 }
576
577 /* EvJobPageData */
578 static void
579 ev_job_page_data_init (EvJobPageData *job)
580 {
581         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
582 }
583
584 static gboolean
585 ev_job_page_data_run (EvJob *job)
586 {
587         EvJobPageData *job_pd = EV_JOB_PAGE_DATA (job);
588         EvPage        *ev_page;
589
590         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_pd->page, job);
591         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
592
593         ev_document_doc_mutex_lock ();
594         ev_page = ev_document_get_page (job->document, job_pd->page);
595
596         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT) && EV_IS_SELECTION (job->document))
597                 job_pd->text_mapping =
598                         ev_selection_get_selection_map (EV_SELECTION (job->document), ev_page);
599         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
600                 job_pd->link_mapping =
601                         ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_pd->page);
602         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
603                 job_pd->form_field_mapping =
604                         ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
605                                                            ev_page);
606         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
607                 job_pd->image_mapping =
608                         ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
609                                                               job_pd->page);
610         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document))
611                 job_pd->annot_mapping =
612                         ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document),
613                                                                  ev_page);
614         g_object_unref (ev_page);
615         ev_document_doc_mutex_unlock ();
616
617         ev_job_succeeded (job);
618
619         return FALSE;
620 }
621
622 static void
623 ev_job_page_data_class_init (EvJobPageDataClass *class)
624 {
625         EvJobClass *job_class = EV_JOB_CLASS (class);
626
627         job_class->run = ev_job_page_data_run;
628 }
629
630 EvJob *
631 ev_job_page_data_new (EvDocument        *document,
632                       gint               page,
633                       EvJobPageDataFlags flags)
634 {
635         EvJobPageData *job;
636
637         ev_debug_message (DEBUG_JOBS, "%d", page);
638
639         job = g_object_new (EV_TYPE_JOB_PAGE_DATA, NULL);
640
641         EV_JOB (job)->document = g_object_ref (document);
642         job->page = page;
643         job->flags = flags;
644
645         return EV_JOB (job);
646 }
647
648 /* EvJobThumbnail */
649 static void
650 ev_job_thumbnail_init (EvJobThumbnail *job)
651 {
652         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
653 }
654
655 static void
656 ev_job_thumbnail_dispose (GObject *object)
657 {
658         EvJobThumbnail *job;
659
660         job = EV_JOB_THUMBNAIL (object);
661
662         ev_debug_message (DEBUG_JOBS, "%d (%p)", job->page, job);
663         
664         if (job->thumbnail) {
665                 g_object_unref (job->thumbnail);
666                 job->thumbnail = NULL;
667         }
668
669         (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
670 }
671
672 static gboolean
673 ev_job_thumbnail_run (EvJob *job)
674 {
675         EvJobThumbnail  *job_thumb = EV_JOB_THUMBNAIL (job);
676         EvRenderContext *rc;
677         EvPage          *page;
678
679         ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
680         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
681         
682         ev_document_doc_mutex_lock ();
683
684         page = ev_document_get_page (job->document, job_thumb->page);
685         rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
686         g_object_unref (page);
687
688         job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
689                                                                      rc, TRUE);
690         g_object_unref (rc);
691         ev_document_doc_mutex_unlock ();
692
693         ev_job_succeeded (job);
694         
695         return FALSE;
696 }
697
698 static void
699 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
700 {
701         GObjectClass *oclass = G_OBJECT_CLASS (class);
702         EvJobClass   *job_class = EV_JOB_CLASS (class);
703
704         oclass->dispose = ev_job_thumbnail_dispose;
705         job_class->run = ev_job_thumbnail_run;
706 }
707
708 EvJob *
709 ev_job_thumbnail_new (EvDocument *document,
710                       gint        page,
711                       gint        rotation,
712                       gdouble     scale)
713 {
714         EvJobThumbnail *job;
715
716         ev_debug_message (DEBUG_JOBS, "%d", page);
717         
718         job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
719
720         EV_JOB (job)->document = g_object_ref (document);
721         job->page = page;
722         job->rotation = rotation;
723         job->scale = scale;
724
725         return EV_JOB (job);
726 }
727
728 /* EvJobFonts */
729 static void
730 ev_job_fonts_init (EvJobFonts *job)
731 {
732         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
733 }
734
735 static gboolean
736 ev_job_fonts_run (EvJob *job)
737 {
738         EvJobFonts      *job_fonts = EV_JOB_FONTS (job);
739         EvDocumentFonts *fonts = EV_DOCUMENT_FONTS (job->document);
740
741         ev_debug_message (DEBUG_JOBS, NULL);
742         
743         /* Do not block the main loop */
744         if (!ev_document_doc_mutex_trylock ())
745                 return TRUE;
746         
747         if (!ev_document_fc_mutex_trylock ())
748                 return TRUE;
749
750 #ifdef EV_ENABLE_DEBUG
751         /* We use the #ifdef in this case because of the if */
752         if (ev_document_fonts_get_progress (fonts) == 0)
753                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
754 #endif
755
756         job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
757         g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
758                        ev_document_fonts_get_progress (fonts));
759
760         ev_document_fc_mutex_unlock ();
761         ev_document_doc_mutex_unlock ();
762
763         if (job_fonts->scan_completed)
764                 ev_job_succeeded (job);
765         
766         return !job_fonts->scan_completed;
767 }
768
769 static void
770 ev_job_fonts_class_init (EvJobFontsClass *class)
771 {
772         EvJobClass *job_class = EV_JOB_CLASS (class);
773         
774         job_class->run = ev_job_fonts_run;
775         
776         job_fonts_signals[FONTS_UPDATED] =
777                 g_signal_new ("updated",
778                               EV_TYPE_JOB_FONTS,
779                               G_SIGNAL_RUN_LAST,
780                               G_STRUCT_OFFSET (EvJobFontsClass, updated),
781                               NULL, NULL,
782                               g_cclosure_marshal_VOID__DOUBLE,
783                               G_TYPE_NONE,
784                               1, G_TYPE_DOUBLE);
785 }
786
787 EvJob *
788 ev_job_fonts_new (EvDocument *document)
789 {
790         EvJobFonts *job;
791
792         ev_debug_message (DEBUG_JOBS, NULL);
793         
794         job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
795
796         EV_JOB (job)->document = g_object_ref (document);
797
798         return EV_JOB (job);
799 }
800
801 /* EvJobLoad */
802 static void
803 ev_job_load_init (EvJobLoad *job)
804 {
805         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
806 }
807
808 static void
809 ev_job_load_dispose (GObject *object)
810 {
811         EvJobLoad *job = EV_JOB_LOAD (object);
812
813         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
814         
815         if (job->uri) {
816                 g_free (job->uri);
817                 job->uri = NULL;
818         }
819
820         if (job->password) {
821                 g_free (job->password);
822                 job->password = NULL;
823         }
824
825         (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
826 }
827
828 static gboolean
829 ev_job_load_run (EvJob *job)
830 {
831         EvJobLoad *job_load = EV_JOB_LOAD (job);
832         GError    *error = NULL;
833         
834         ev_debug_message (DEBUG_JOBS, "%s", job_load->uri);
835         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
836         
837         ev_document_fc_mutex_lock ();
838
839         /* This job may already have a document even if the job didn't complete
840            because, e.g., a password is required - if so, just reload rather than
841            creating a new instance */
842         if (job->document) {
843                 if (job_load->password) {
844                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
845                                                            job_load->password);
846                 }
847                 
848                 job->failed = FALSE;
849                 job->finished = FALSE;
850                 g_clear_error (&job->error);
851                 
852                 ev_document_load (job->document,
853                                   job_load->uri,
854                                   &error);
855         } else {
856                 job->document = ev_document_factory_get_document (job_load->uri,
857                                                                   &error);
858         }
859
860         ev_document_fc_mutex_unlock ();
861
862         if (error) {
863                 ev_job_failed_from_error (job, error);
864                 g_error_free (error);
865         } else {
866                 ev_job_succeeded (job);
867         }
868
869         return FALSE;
870 }
871
872 static void
873 ev_job_load_class_init (EvJobLoadClass *class)
874 {
875         GObjectClass *oclass = G_OBJECT_CLASS (class);
876         EvJobClass   *job_class = EV_JOB_CLASS (class);
877
878         oclass->dispose = ev_job_load_dispose;
879         job_class->run = ev_job_load_run;
880 }
881
882 EvJob *
883 ev_job_load_new (const gchar *uri)
884 {
885         EvJobLoad *job;
886
887         ev_debug_message (DEBUG_JOBS, "%s", uri);
888         
889         job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
890         job->uri = g_strdup (uri);
891
892         return EV_JOB (job);
893 }
894
895 void
896 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
897 {
898         ev_debug_message (DEBUG_JOBS, "%s", uri);
899         
900         if (job->uri)
901                 g_free (job->uri);
902         job->uri = g_strdup (uri);
903 }
904
905 void
906 ev_job_load_set_password (EvJobLoad *job, const gchar *password)
907 {
908         ev_debug_message (DEBUG_JOBS, NULL);
909
910         if (job->password)
911                 g_free (job->password);
912         job->password = password ? g_strdup (password) : NULL;
913 }
914
915 /* EvJobSave */
916 static void
917 ev_job_save_init (EvJobSave *job)
918 {
919         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
920 }
921
922 static void
923 ev_job_save_dispose (GObject *object)
924 {
925         EvJobSave *job = EV_JOB_SAVE (object);
926
927         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
928         
929         if (job->uri) {
930                 g_free (job->uri);
931                 job->uri = NULL;
932         }
933
934         if (job->document_uri) {
935                 g_free (job->document_uri);
936                 job->document_uri = NULL;
937         }
938
939         (* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
940 }
941
942 static gboolean
943 ev_job_save_run (EvJob *job)
944 {
945         EvJobSave *job_save = EV_JOB_SAVE (job);
946         gint       fd;
947         gchar     *tmp_filename = NULL;
948         gchar     *local_uri;
949         GError    *error = NULL;
950         
951         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
952         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
953
954         fd = ev_mkstemp ("saveacopy.XXXXXX", &tmp_filename, &error);
955         if (fd == -1) {
956                 ev_job_failed_from_error (job, error);
957                 g_error_free (error);
958
959                 return FALSE;
960         }
961
962         ev_document_doc_mutex_lock ();
963
964         /* Save document to temp filename */
965         local_uri = g_filename_to_uri (tmp_filename, NULL, &error);
966         if (local_uri != NULL) {
967                 ev_document_save (job->document, local_uri, &error);
968         }
969
970         close (fd);
971
972         ev_document_doc_mutex_unlock ();
973
974         if (error) {
975                 g_free (local_uri);
976                 ev_job_failed_from_error (job, error);
977                 g_error_free (error);
978                 
979                 return FALSE;
980         }
981
982         /* If original document was compressed,
983          * compress it again before saving
984          */
985         if (g_object_get_data (G_OBJECT (job->document), "uri-uncompressed")) {
986                 EvCompressionType ctype = EV_COMPRESSION_NONE;
987                 const gchar      *ext;
988                 gchar            *uri_comp;
989                 
990                 ext = g_strrstr (job_save->document_uri, ".gz");
991                 if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
992                         ctype = EV_COMPRESSION_GZIP;
993                 
994                 ext = g_strrstr (job_save->document_uri, ".bz2");
995                 if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
996                         ctype = EV_COMPRESSION_BZIP2;
997
998                 uri_comp = ev_file_compress (local_uri, ctype, &error);
999                 g_free (local_uri);
1000                 g_unlink (tmp_filename);
1001
1002                 if (!uri_comp || error) {
1003                         local_uri = NULL;
1004                 } else {
1005                         local_uri = uri_comp;
1006                 }
1007         }
1008
1009         g_free (tmp_filename);
1010
1011         if (error) {
1012                 g_free (local_uri);
1013                 ev_job_failed_from_error (job, error);
1014                 g_error_free (error);
1015                 
1016                 return FALSE;
1017         }
1018
1019         if (!local_uri)
1020                 return FALSE;
1021
1022         ev_xfer_uri_simple (local_uri, job_save->uri, &error);
1023         ev_tmp_uri_unlink (local_uri);
1024
1025         if (error) {
1026                 ev_job_failed_from_error (job, error);
1027                 g_error_free (error);
1028         } else {
1029                 ev_job_succeeded (job);
1030         }
1031         
1032         return FALSE;
1033 }
1034
1035 static void
1036 ev_job_save_class_init (EvJobSaveClass *class)
1037 {
1038         GObjectClass *oclass = G_OBJECT_CLASS (class);
1039         EvJobClass   *job_class = EV_JOB_CLASS (class);
1040
1041         oclass->dispose = ev_job_save_dispose;
1042         job_class->run = ev_job_save_run;
1043 }
1044
1045 EvJob *
1046 ev_job_save_new (EvDocument  *document,
1047                  const gchar *uri,
1048                  const gchar *document_uri)
1049 {
1050         EvJobSave *job;
1051
1052         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
1053
1054         job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
1055
1056         EV_JOB (job)->document = g_object_ref (document);
1057         job->uri = g_strdup (uri);
1058         job->document_uri = g_strdup (document_uri);
1059
1060         return EV_JOB (job);
1061 }
1062
1063 /* EvJobFind */
1064 static void
1065 ev_job_find_init (EvJobFind *job)
1066 {
1067         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
1068 }
1069
1070 static void
1071 ev_job_find_dispose (GObject *object)
1072 {
1073         EvJobFind *job = EV_JOB_FIND (object);
1074
1075         ev_debug_message (DEBUG_JOBS, NULL);
1076
1077         if (job->text) {
1078                 g_free (job->text);
1079                 job->text = NULL;
1080         }
1081
1082         if (job->pages) {
1083                 gint i;
1084
1085                 for (i = 0; i < job->n_pages; i++) {
1086                         g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
1087                         g_list_free (job->pages[i]);
1088                 }
1089
1090                 g_free (job->pages);
1091                 job->pages = NULL;
1092         }
1093         
1094         (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
1095 }
1096
1097 static gboolean
1098 ev_job_find_run (EvJob *job)
1099 {
1100         EvJobFind      *job_find = EV_JOB_FIND (job);
1101         EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
1102         EvPage         *ev_page;
1103         GList          *matches;
1104
1105         ev_debug_message (DEBUG_JOBS, NULL);
1106         
1107         /* Do not block the main loop */
1108         if (!ev_document_doc_mutex_trylock ())
1109                 return TRUE;
1110         
1111 #ifdef EV_ENABLE_DEBUG
1112         /* We use the #ifdef in this case because of the if */
1113         if (job_find->current_page == job_find->start_page)
1114                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1115 #endif
1116
1117         ev_page = ev_document_get_page (job->document, job_find->current_page);
1118         matches = ev_document_find_find_text (find, ev_page, job_find->text,
1119                                               job_find->case_sensitive);
1120         g_object_unref (ev_page);
1121         
1122         ev_document_doc_mutex_unlock ();
1123
1124         if (!job_find->has_results)
1125                 job_find->has_results = (matches != NULL);
1126
1127         job_find->pages[job_find->current_page] = matches;
1128         g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
1129                        
1130         job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
1131         if (job_find->current_page == job_find->start_page) {
1132                 ev_job_succeeded (job);
1133
1134                 return FALSE;
1135         }
1136
1137         return TRUE;
1138 }
1139
1140 static void
1141 ev_job_find_class_init (EvJobFindClass *class)
1142 {
1143         EvJobClass   *job_class = EV_JOB_CLASS (class);
1144         GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1145         
1146         job_class->run = ev_job_find_run;
1147         gobject_class->dispose = ev_job_find_dispose;
1148         
1149         job_find_signals[FIND_UPDATED] =
1150                 g_signal_new ("updated",
1151                               EV_TYPE_JOB_FIND,
1152                               G_SIGNAL_RUN_LAST,
1153                               G_STRUCT_OFFSET (EvJobFindClass, updated),
1154                               NULL, NULL,
1155                               g_cclosure_marshal_VOID__INT,
1156                               G_TYPE_NONE,
1157                               1, G_TYPE_INT);
1158 }
1159
1160 EvJob *
1161 ev_job_find_new (EvDocument  *document,
1162                  gint         start_page,
1163                  gint         n_pages,
1164                  const gchar *text,
1165                  gboolean     case_sensitive)
1166 {
1167         EvJobFind *job;
1168         
1169         ev_debug_message (DEBUG_JOBS, NULL);
1170         
1171         job = g_object_new (EV_TYPE_JOB_FIND, NULL);
1172
1173         EV_JOB (job)->document = g_object_ref (document);
1174         job->start_page = start_page;
1175         job->current_page = start_page;
1176         job->n_pages = n_pages;
1177         job->pages = g_new0 (GList *, n_pages);
1178         job->text = g_strdup (text);
1179         job->case_sensitive = case_sensitive;
1180         job->has_results = FALSE;
1181
1182         return EV_JOB (job);
1183 }
1184
1185 gint
1186 ev_job_find_get_n_results (EvJobFind *job,
1187                            gint       page)
1188 {
1189         return g_list_length (job->pages[page]);
1190 }
1191
1192 gdouble
1193 ev_job_find_get_progress (EvJobFind *job)
1194 {
1195         gint pages_done;
1196
1197         if (ev_job_is_finished (EV_JOB (job)))
1198                 return 1.0;
1199         
1200         if (job->current_page > job->start_page) {
1201                 pages_done = job->current_page - job->start_page + 1;
1202         } else if (job->current_page == job->start_page) {
1203                 pages_done = job->n_pages;
1204         } else {
1205                 pages_done = job->n_pages - job->start_page + job->current_page;
1206         }
1207
1208         return pages_done / (gdouble) job->n_pages;
1209 }
1210
1211 gboolean
1212 ev_job_find_has_results (EvJobFind *job)
1213 {
1214         return job->has_results;
1215 }
1216
1217 GList **
1218 ev_job_find_get_results (EvJobFind *job)
1219 {
1220         return job->pages;
1221 }
1222
1223 /* EvJobLayers */
1224 static void
1225 ev_job_layers_init (EvJobLayers *job)
1226 {
1227         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1228 }
1229
1230 static void
1231 ev_job_layers_dispose (GObject *object)
1232 {
1233         EvJobLayers *job;
1234
1235         ev_debug_message (DEBUG_JOBS, NULL);
1236         
1237         job = EV_JOB_LAYERS (object);
1238
1239         if (job->model) {
1240                 g_object_unref (job->model);
1241                 job->model = NULL;
1242         }
1243
1244         (* G_OBJECT_CLASS (ev_job_layers_parent_class)->dispose) (object);
1245 }
1246
1247 static gboolean
1248 ev_job_layers_run (EvJob *job)
1249 {
1250         EvJobLayers *job_layers = EV_JOB_LAYERS (job);
1251
1252         ev_debug_message (DEBUG_JOBS, NULL);
1253         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1254         
1255         ev_document_doc_mutex_lock ();
1256         job_layers->model = ev_document_layers_get_layers (EV_DOCUMENT_LAYERS (job->document));
1257         ev_document_doc_mutex_unlock ();
1258         
1259         ev_job_succeeded (job);
1260         
1261         return FALSE;
1262 }
1263
1264 static void
1265 ev_job_layers_class_init (EvJobLayersClass *class)
1266 {
1267         GObjectClass *oclass = G_OBJECT_CLASS (class);
1268         EvJobClass   *job_class = EV_JOB_CLASS (class);
1269
1270         oclass->dispose = ev_job_layers_dispose;
1271         job_class->run = ev_job_layers_run;
1272 }
1273
1274 EvJob *
1275 ev_job_layers_new (EvDocument *document)
1276 {
1277         EvJob *job;
1278
1279         ev_debug_message (DEBUG_JOBS, NULL);
1280
1281         job = g_object_new (EV_TYPE_JOB_LAYERS, NULL);
1282         job->document = g_object_ref (document);
1283         
1284         return job;
1285 }
1286
1287 /* EvJobExport */
1288 static void
1289 ev_job_export_init (EvJobExport *job)
1290 {
1291         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1292         job->page = -1;
1293 }
1294
1295 static void
1296 ev_job_export_dispose (GObject *object)
1297 {
1298         EvJobExport *job;
1299
1300         ev_debug_message (DEBUG_JOBS, NULL);
1301         
1302         job = EV_JOB_EXPORT (object);
1303
1304         if (job->rc) {
1305                 g_object_unref (job->rc);
1306                 job->rc = NULL;
1307         }
1308
1309         (* G_OBJECT_CLASS (ev_job_export_parent_class)->dispose) (object);
1310 }
1311
1312 static gboolean
1313 ev_job_export_run (EvJob *job)
1314 {
1315         EvJobExport *job_export = EV_JOB_EXPORT (job);
1316         EvPage      *ev_page;
1317
1318         g_assert (job_export->page != -1);
1319
1320         ev_debug_message (DEBUG_JOBS, NULL);
1321         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1322         
1323         ev_document_doc_mutex_lock ();
1324         
1325         ev_page = ev_document_get_page (job->document, job_export->page);
1326         if (job_export->rc) {
1327                 job->failed = FALSE;
1328                 job->finished = FALSE;
1329                 g_clear_error (&job->error);
1330                 
1331                 ev_render_context_set_page (job_export->rc, ev_page);
1332         } else {
1333                 job_export->rc = ev_render_context_new (ev_page, 0, 1.0);
1334         }
1335         g_object_unref (ev_page);
1336         
1337         ev_file_exporter_do_page (EV_FILE_EXPORTER (job->document), job_export->rc);
1338         
1339         ev_document_doc_mutex_unlock ();
1340         
1341         ev_job_succeeded (job);
1342         
1343         return FALSE;
1344 }
1345
1346 static void
1347 ev_job_export_class_init (EvJobExportClass *class)
1348 {
1349         GObjectClass *oclass = G_OBJECT_CLASS (class);
1350         EvJobClass   *job_class = EV_JOB_CLASS (class);
1351
1352         oclass->dispose = ev_job_export_dispose;
1353         job_class->run = ev_job_export_run;
1354 }
1355
1356 EvJob *
1357 ev_job_export_new (EvDocument *document)
1358 {
1359         EvJob *job;
1360
1361         ev_debug_message (DEBUG_JOBS, NULL);
1362
1363         job = g_object_new (EV_TYPE_JOB_EXPORT, NULL);
1364         job->document = g_object_ref (document);
1365         
1366         return job;
1367 }
1368
1369 void
1370 ev_job_export_set_page (EvJobExport *job,
1371                         gint         page)
1372 {
1373         job->page = page;
1374 }
1375
1376 /* EvJobPrint */
1377 static void
1378 ev_job_print_init (EvJobPrint *job)
1379 {
1380         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1381         job->page = -1;
1382 }
1383
1384 static void
1385 ev_job_print_dispose (GObject *object)
1386 {
1387         EvJobPrint *job;
1388
1389         ev_debug_message (DEBUG_JOBS, NULL);
1390
1391         job = EV_JOB_PRINT (object);
1392
1393         if (job->cr) {
1394                 cairo_destroy (job->cr);
1395                 job->cr = NULL;
1396         }
1397
1398         (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
1399 }
1400
1401 static gboolean
1402 ev_job_print_run (EvJob *job)
1403 {
1404         EvJobPrint     *job_print = EV_JOB_PRINT (job);
1405         EvPage         *ev_page;
1406         cairo_status_t  cr_status;
1407
1408         g_assert (job_print->page != -1);
1409         g_assert (job_print->cr != NULL);
1410
1411         ev_debug_message (DEBUG_JOBS, NULL);
1412         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1413
1414         job->failed = FALSE;
1415         job->finished = FALSE;
1416         g_clear_error (&job->error);
1417
1418         ev_document_doc_mutex_lock ();
1419
1420         ev_page = ev_document_get_page (job->document, job_print->page);
1421         ev_document_print_print_page (EV_DOCUMENT_PRINT (job->document),
1422                                       ev_page, job_print->cr);
1423         g_object_unref (ev_page);
1424
1425         ev_document_doc_mutex_unlock ();
1426
1427         cr_status = cairo_status (job_print->cr);
1428         if (cr_status == CAIRO_STATUS_SUCCESS) {
1429                 ev_job_succeeded (job);
1430         } else {
1431                 ev_job_failed (job,
1432                                GTK_PRINT_ERROR,
1433                                GTK_PRINT_ERROR_GENERAL,
1434                                _("Failed to print page %d: %s"),
1435                                job_print->page,
1436                                cairo_status_to_string (cr_status));
1437         }
1438
1439         return FALSE;
1440 }
1441
1442 static void
1443 ev_job_print_class_init (EvJobPrintClass *class)
1444 {
1445         GObjectClass *oclass = G_OBJECT_CLASS (class);
1446         EvJobClass   *job_class = EV_JOB_CLASS (class);
1447
1448         oclass->dispose = ev_job_print_dispose;
1449         job_class->run = ev_job_print_run;
1450 }
1451
1452 EvJob *
1453 ev_job_print_new (EvDocument *document)
1454 {
1455         EvJob *job;
1456
1457         ev_debug_message (DEBUG_JOBS, NULL);
1458
1459         job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
1460         job->document = g_object_ref (document);
1461
1462         return job;
1463 }
1464
1465 void
1466 ev_job_print_set_page (EvJobPrint *job,
1467                        gint        page)
1468 {
1469         job->page = page;
1470 }
1471
1472 void
1473 ev_job_print_set_cairo (EvJobPrint *job,
1474                         cairo_t    *cr)
1475 {
1476         if (job->cr == cr)
1477                 return;
1478
1479         if (job->cr)
1480                 cairo_destroy (job->cr);
1481         job->cr = cr ? cairo_reference (cr) : NULL;
1482 }