]> www.fi.muni.cz Git - evince.git/blob - libview/ev-jobs.c
[libview] Split EvPixbufCache into dynamic and static data
[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         if (job->ev_page) {
452                 ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->ev_page->index, job);
453                 g_object_unref (job->ev_page);
454                 job->ev_page = NULL;
455         }
456         
457         if (job->surface) {
458                 cairo_surface_destroy (job->surface);
459                 job->surface = NULL;
460         }
461
462         if (job->selection) {
463                 cairo_surface_destroy (job->selection);
464                 job->selection = NULL;
465         }
466
467         if (job->selection_region) {
468                 gdk_region_destroy (job->selection_region);
469                 job->selection_region = NULL;
470         }
471
472         (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
473 }
474
475 static gboolean
476 ev_job_render_run (EvJob *job)
477 {
478         EvJobRender     *job_render = EV_JOB_RENDER (job);
479         EvRenderContext *rc;
480
481         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
482         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
483         
484         ev_document_doc_mutex_lock ();
485
486         ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job_render->page);
487                 
488         ev_document_fc_mutex_lock ();
489
490         job_render->ev_page = ev_document_get_page (job->document, job_render->page);
491         rc = ev_render_context_new (job_render->ev_page, job_render->rotation, job_render->scale);
492                 
493         job_render->surface = ev_document_render (job->document, rc);
494         /* If job was cancelled during the page rendering,
495          * we return now, so that the thread is finished ASAP
496          */
497         if (g_cancellable_is_cancelled (job->cancellable)) {
498                 ev_document_fc_mutex_unlock ();
499                 ev_document_doc_mutex_unlock ();
500                 g_object_unref (rc);
501
502                 return FALSE;
503         }
504
505         if (job_render->include_selection && EV_IS_SELECTION (job->document)) {
506                 ev_selection_render_selection (EV_SELECTION (job->document),
507                                                rc,
508                                                &(job_render->selection),
509                                                &(job_render->selection_points),
510                                                NULL,
511                                                job_render->selection_style,
512                                                &(job_render->text), &(job_render->base));
513                 job_render->selection_region =
514                         ev_selection_get_selection_region (EV_SELECTION (job->document),
515                                                            rc,
516                                                            job_render->selection_style,
517                                                            &(job_render->selection_points));
518         }
519
520         g_object_unref (rc);
521
522         ev_document_fc_mutex_unlock ();
523         ev_document_doc_mutex_unlock ();
524         
525         ev_job_succeeded (job);
526         
527         return FALSE;
528 }
529
530 static void
531 ev_job_render_class_init (EvJobRenderClass *class)
532 {
533         GObjectClass *oclass = G_OBJECT_CLASS (class);
534         EvJobClass   *job_class = EV_JOB_CLASS (class);
535
536         oclass->dispose = ev_job_render_dispose;
537         job_class->run = ev_job_render_run;
538 }
539
540 EvJob *
541 ev_job_render_new (EvDocument   *document,
542                    gint          page,
543                    gint          rotation,
544                    gdouble       scale,
545                    gint          width,
546                    gint          height)
547 {
548         EvJobRender *job;
549
550         ev_debug_message (DEBUG_JOBS, "page: %d", page);
551         
552         job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
553
554         EV_JOB (job)->document = g_object_ref (document);
555         job->page = page;
556         job->rotation = rotation;
557         job->scale = scale;
558         job->target_width = width;
559         job->target_height = height;
560
561         return EV_JOB (job);
562 }
563
564 void
565 ev_job_render_set_selection_info (EvJobRender     *job,
566                                   EvRectangle     *selection_points,
567                                   EvSelectionStyle selection_style,
568                                   GdkColor        *text,
569                                   GdkColor        *base)
570 {
571         job->include_selection = TRUE;
572
573         job->selection_points = *selection_points;
574         job->selection_style = selection_style;
575         job->text = *text;
576         job->base = *base;
577 }
578
579 /* EvJobPageData */
580 static void
581 ev_job_page_data_init (EvJobPageData *job)
582 {
583         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
584 }
585
586 static gboolean
587 ev_job_page_data_run (EvJob *job)
588 {
589         EvJobPageData *job_pd = EV_JOB_PAGE_DATA (job);
590         EvPage        *ev_page;
591
592         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_pd->page, job);
593         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
594
595         ev_document_doc_mutex_lock ();
596         ev_page = ev_document_get_page (job->document, job_pd->page);
597
598         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT) && EV_IS_SELECTION (job->document))
599                 job_pd->text_mapping =
600                         ev_selection_get_selection_map (EV_SELECTION (job->document), ev_page);
601         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
602                 job_pd->link_mapping =
603                         ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_pd->page);
604         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
605                 job_pd->form_field_mapping =
606                         ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
607                                                            ev_page);
608         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
609                 job_pd->image_mapping =
610                         ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
611                                                               job_pd->page);
612         if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document))
613                 job_pd->annot_mapping =
614                         ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document),
615                                                                  ev_page);
616         g_object_unref (ev_page);
617         ev_document_doc_mutex_unlock ();
618
619         ev_job_succeeded (job);
620
621         return FALSE;
622 }
623
624 static void
625 ev_job_page_data_class_init (EvJobPageDataClass *class)
626 {
627         EvJobClass *job_class = EV_JOB_CLASS (class);
628
629         job_class->run = ev_job_page_data_run;
630 }
631
632 EvJob *
633 ev_job_page_data_new (EvDocument        *document,
634                       gint               page,
635                       EvJobPageDataFlags flags)
636 {
637         EvJobPageData *job;
638
639         ev_debug_message (DEBUG_JOBS, "%d", page);
640
641         job = g_object_new (EV_TYPE_JOB_PAGE_DATA, NULL);
642
643         EV_JOB (job)->document = g_object_ref (document);
644         job->page = page;
645         job->flags = flags;
646
647         return EV_JOB (job);
648 }
649
650 /* EvJobThumbnail */
651 static void
652 ev_job_thumbnail_init (EvJobThumbnail *job)
653 {
654         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
655 }
656
657 static void
658 ev_job_thumbnail_dispose (GObject *object)
659 {
660         EvJobThumbnail *job;
661
662         job = EV_JOB_THUMBNAIL (object);
663
664         ev_debug_message (DEBUG_JOBS, "%d (%p)", job->page, job);
665         
666         if (job->thumbnail) {
667                 g_object_unref (job->thumbnail);
668                 job->thumbnail = NULL;
669         }
670
671         (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
672 }
673
674 static gboolean
675 ev_job_thumbnail_run (EvJob *job)
676 {
677         EvJobThumbnail  *job_thumb = EV_JOB_THUMBNAIL (job);
678         EvRenderContext *rc;
679         EvPage          *page;
680
681         ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
682         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
683         
684         ev_document_doc_mutex_lock ();
685
686         page = ev_document_get_page (job->document, job_thumb->page);
687         rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
688         g_object_unref (page);
689
690         job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
691                                                                      rc, TRUE);
692         g_object_unref (rc);
693         ev_document_doc_mutex_unlock ();
694
695         ev_job_succeeded (job);
696         
697         return FALSE;
698 }
699
700 static void
701 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
702 {
703         GObjectClass *oclass = G_OBJECT_CLASS (class);
704         EvJobClass   *job_class = EV_JOB_CLASS (class);
705
706         oclass->dispose = ev_job_thumbnail_dispose;
707         job_class->run = ev_job_thumbnail_run;
708 }
709
710 EvJob *
711 ev_job_thumbnail_new (EvDocument *document,
712                       gint        page,
713                       gint        rotation,
714                       gdouble     scale)
715 {
716         EvJobThumbnail *job;
717
718         ev_debug_message (DEBUG_JOBS, "%d", page);
719         
720         job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
721
722         EV_JOB (job)->document = g_object_ref (document);
723         job->page = page;
724         job->rotation = rotation;
725         job->scale = scale;
726
727         return EV_JOB (job);
728 }
729
730 /* EvJobFonts */
731 static void
732 ev_job_fonts_init (EvJobFonts *job)
733 {
734         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
735 }
736
737 static gboolean
738 ev_job_fonts_run (EvJob *job)
739 {
740         EvJobFonts      *job_fonts = EV_JOB_FONTS (job);
741         EvDocumentFonts *fonts = EV_DOCUMENT_FONTS (job->document);
742
743         ev_debug_message (DEBUG_JOBS, NULL);
744         
745         /* Do not block the main loop */
746         if (!ev_document_doc_mutex_trylock ())
747                 return TRUE;
748         
749         if (!ev_document_fc_mutex_trylock ())
750                 return TRUE;
751
752 #ifdef EV_ENABLE_DEBUG
753         /* We use the #ifdef in this case because of the if */
754         if (ev_document_fonts_get_progress (fonts) == 0)
755                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
756 #endif
757
758         job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
759         g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
760                        ev_document_fonts_get_progress (fonts));
761
762         ev_document_fc_mutex_unlock ();
763         ev_document_doc_mutex_unlock ();
764
765         if (job_fonts->scan_completed)
766                 ev_job_succeeded (job);
767         
768         return !job_fonts->scan_completed;
769 }
770
771 static void
772 ev_job_fonts_class_init (EvJobFontsClass *class)
773 {
774         EvJobClass *job_class = EV_JOB_CLASS (class);
775         
776         job_class->run = ev_job_fonts_run;
777         
778         job_fonts_signals[FONTS_UPDATED] =
779                 g_signal_new ("updated",
780                               EV_TYPE_JOB_FONTS,
781                               G_SIGNAL_RUN_LAST,
782                               G_STRUCT_OFFSET (EvJobFontsClass, updated),
783                               NULL, NULL,
784                               g_cclosure_marshal_VOID__DOUBLE,
785                               G_TYPE_NONE,
786                               1, G_TYPE_DOUBLE);
787 }
788
789 EvJob *
790 ev_job_fonts_new (EvDocument *document)
791 {
792         EvJobFonts *job;
793
794         ev_debug_message (DEBUG_JOBS, NULL);
795         
796         job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
797
798         EV_JOB (job)->document = g_object_ref (document);
799
800         return EV_JOB (job);
801 }
802
803 /* EvJobLoad */
804 static void
805 ev_job_load_init (EvJobLoad *job)
806 {
807         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
808 }
809
810 static void
811 ev_job_load_dispose (GObject *object)
812 {
813         EvJobLoad *job = EV_JOB_LOAD (object);
814
815         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
816         
817         if (job->uri) {
818                 g_free (job->uri);
819                 job->uri = NULL;
820         }
821
822         if (job->password) {
823                 g_free (job->password);
824                 job->password = NULL;
825         }
826
827         (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
828 }
829
830 static gboolean
831 ev_job_load_run (EvJob *job)
832 {
833         EvJobLoad *job_load = EV_JOB_LOAD (job);
834         GError    *error = NULL;
835         
836         ev_debug_message (DEBUG_JOBS, "%s", job_load->uri);
837         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
838         
839         ev_document_fc_mutex_lock ();
840
841         /* This job may already have a document even if the job didn't complete
842            because, e.g., a password is required - if so, just reload rather than
843            creating a new instance */
844         if (job->document) {
845                 if (job_load->password) {
846                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
847                                                            job_load->password);
848                 }
849                 
850                 job->failed = FALSE;
851                 job->finished = FALSE;
852                 g_clear_error (&job->error);
853                 
854                 ev_document_load (job->document,
855                                   job_load->uri,
856                                   &error);
857         } else {
858                 job->document = ev_document_factory_get_document (job_load->uri,
859                                                                   &error);
860         }
861
862         ev_document_fc_mutex_unlock ();
863
864         if (error) {
865                 ev_job_failed_from_error (job, error);
866                 g_error_free (error);
867         } else {
868                 ev_job_succeeded (job);
869         }
870
871         return FALSE;
872 }
873
874 static void
875 ev_job_load_class_init (EvJobLoadClass *class)
876 {
877         GObjectClass *oclass = G_OBJECT_CLASS (class);
878         EvJobClass   *job_class = EV_JOB_CLASS (class);
879
880         oclass->dispose = ev_job_load_dispose;
881         job_class->run = ev_job_load_run;
882 }
883
884 EvJob *
885 ev_job_load_new (const gchar *uri)
886 {
887         EvJobLoad *job;
888
889         ev_debug_message (DEBUG_JOBS, "%s", uri);
890         
891         job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
892         job->uri = g_strdup (uri);
893
894         return EV_JOB (job);
895 }
896
897 void
898 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
899 {
900         ev_debug_message (DEBUG_JOBS, "%s", uri);
901         
902         if (job->uri)
903                 g_free (job->uri);
904         job->uri = g_strdup (uri);
905 }
906
907 void
908 ev_job_load_set_password (EvJobLoad *job, const gchar *password)
909 {
910         ev_debug_message (DEBUG_JOBS, NULL);
911
912         if (job->password)
913                 g_free (job->password);
914         job->password = password ? g_strdup (password) : NULL;
915 }
916
917 /* EvJobSave */
918 static void
919 ev_job_save_init (EvJobSave *job)
920 {
921         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
922 }
923
924 static void
925 ev_job_save_dispose (GObject *object)
926 {
927         EvJobSave *job = EV_JOB_SAVE (object);
928
929         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
930         
931         if (job->uri) {
932                 g_free (job->uri);
933                 job->uri = NULL;
934         }
935
936         if (job->document_uri) {
937                 g_free (job->document_uri);
938                 job->document_uri = NULL;
939         }
940
941         (* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
942 }
943
944 static gboolean
945 ev_job_save_run (EvJob *job)
946 {
947         EvJobSave *job_save = EV_JOB_SAVE (job);
948         gint       fd;
949         gchar     *tmp_filename = NULL;
950         gchar     *local_uri;
951         GError    *error = NULL;
952         
953         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
954         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
955
956         fd = ev_mkstemp ("saveacopy.XXXXXX", &tmp_filename, &error);
957         if (fd == -1) {
958                 ev_job_failed_from_error (job, error);
959                 g_error_free (error);
960
961                 return FALSE;
962         }
963
964         ev_document_doc_mutex_lock ();
965
966         /* Save document to temp filename */
967         local_uri = g_filename_to_uri (tmp_filename, NULL, &error);
968         if (local_uri != NULL) {
969                 ev_document_save (job->document, local_uri, &error);
970         }
971
972         close (fd);
973
974         ev_document_doc_mutex_unlock ();
975
976         if (error) {
977                 g_free (local_uri);
978                 ev_job_failed_from_error (job, error);
979                 g_error_free (error);
980                 
981                 return FALSE;
982         }
983
984         /* If original document was compressed,
985          * compress it again before saving
986          */
987         if (g_object_get_data (G_OBJECT (job->document), "uri-uncompressed")) {
988                 EvCompressionType ctype = EV_COMPRESSION_NONE;
989                 const gchar      *ext;
990                 gchar            *uri_comp;
991                 
992                 ext = g_strrstr (job_save->document_uri, ".gz");
993                 if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
994                         ctype = EV_COMPRESSION_GZIP;
995                 
996                 ext = g_strrstr (job_save->document_uri, ".bz2");
997                 if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
998                         ctype = EV_COMPRESSION_BZIP2;
999
1000                 uri_comp = ev_file_compress (local_uri, ctype, &error);
1001                 g_free (local_uri);
1002                 g_unlink (tmp_filename);
1003
1004                 if (!uri_comp || error) {
1005                         local_uri = NULL;
1006                 } else {
1007                         local_uri = uri_comp;
1008                 }
1009         }
1010
1011         g_free (tmp_filename);
1012
1013         if (error) {
1014                 g_free (local_uri);
1015                 ev_job_failed_from_error (job, error);
1016                 g_error_free (error);
1017                 
1018                 return FALSE;
1019         }
1020
1021         if (!local_uri)
1022                 return FALSE;
1023
1024         ev_xfer_uri_simple (local_uri, job_save->uri, &error);
1025         ev_tmp_uri_unlink (local_uri);
1026
1027         if (error) {
1028                 ev_job_failed_from_error (job, error);
1029                 g_error_free (error);
1030         } else {
1031                 ev_job_succeeded (job);
1032         }
1033         
1034         return FALSE;
1035 }
1036
1037 static void
1038 ev_job_save_class_init (EvJobSaveClass *class)
1039 {
1040         GObjectClass *oclass = G_OBJECT_CLASS (class);
1041         EvJobClass   *job_class = EV_JOB_CLASS (class);
1042
1043         oclass->dispose = ev_job_save_dispose;
1044         job_class->run = ev_job_save_run;
1045 }
1046
1047 EvJob *
1048 ev_job_save_new (EvDocument  *document,
1049                  const gchar *uri,
1050                  const gchar *document_uri)
1051 {
1052         EvJobSave *job;
1053
1054         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
1055
1056         job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
1057
1058         EV_JOB (job)->document = g_object_ref (document);
1059         job->uri = g_strdup (uri);
1060         job->document_uri = g_strdup (document_uri);
1061
1062         return EV_JOB (job);
1063 }
1064
1065 /* EvJobFind */
1066 static void
1067 ev_job_find_init (EvJobFind *job)
1068 {
1069         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
1070 }
1071
1072 static void
1073 ev_job_find_dispose (GObject *object)
1074 {
1075         EvJobFind *job = EV_JOB_FIND (object);
1076
1077         ev_debug_message (DEBUG_JOBS, NULL);
1078
1079         if (job->text) {
1080                 g_free (job->text);
1081                 job->text = NULL;
1082         }
1083
1084         if (job->pages) {
1085                 gint i;
1086
1087                 for (i = 0; i < job->n_pages; i++) {
1088                         g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
1089                         g_list_free (job->pages[i]);
1090                 }
1091
1092                 g_free (job->pages);
1093                 job->pages = NULL;
1094         }
1095         
1096         (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
1097 }
1098
1099 static gboolean
1100 ev_job_find_run (EvJob *job)
1101 {
1102         EvJobFind      *job_find = EV_JOB_FIND (job);
1103         EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
1104         EvPage         *ev_page;
1105         GList          *matches;
1106
1107         ev_debug_message (DEBUG_JOBS, NULL);
1108         
1109         /* Do not block the main loop */
1110         if (!ev_document_doc_mutex_trylock ())
1111                 return TRUE;
1112         
1113 #ifdef EV_ENABLE_DEBUG
1114         /* We use the #ifdef in this case because of the if */
1115         if (job_find->current_page == job_find->start_page)
1116                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1117 #endif
1118
1119         ev_page = ev_document_get_page (job->document, job_find->current_page);
1120         matches = ev_document_find_find_text (find, ev_page, job_find->text,
1121                                               job_find->case_sensitive);
1122         g_object_unref (ev_page);
1123         
1124         ev_document_doc_mutex_unlock ();
1125
1126         if (!job_find->has_results)
1127                 job_find->has_results = (matches != NULL);
1128
1129         job_find->pages[job_find->current_page] = matches;
1130         g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
1131                        
1132         job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
1133         if (job_find->current_page == job_find->start_page) {
1134                 ev_job_succeeded (job);
1135
1136                 return FALSE;
1137         }
1138
1139         return TRUE;
1140 }
1141
1142 static void
1143 ev_job_find_class_init (EvJobFindClass *class)
1144 {
1145         EvJobClass   *job_class = EV_JOB_CLASS (class);
1146         GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1147         
1148         job_class->run = ev_job_find_run;
1149         gobject_class->dispose = ev_job_find_dispose;
1150         
1151         job_find_signals[FIND_UPDATED] =
1152                 g_signal_new ("updated",
1153                               EV_TYPE_JOB_FIND,
1154                               G_SIGNAL_RUN_LAST,
1155                               G_STRUCT_OFFSET (EvJobFindClass, updated),
1156                               NULL, NULL,
1157                               g_cclosure_marshal_VOID__INT,
1158                               G_TYPE_NONE,
1159                               1, G_TYPE_INT);
1160 }
1161
1162 EvJob *
1163 ev_job_find_new (EvDocument  *document,
1164                  gint         start_page,
1165                  gint         n_pages,
1166                  const gchar *text,
1167                  gboolean     case_sensitive)
1168 {
1169         EvJobFind *job;
1170         
1171         ev_debug_message (DEBUG_JOBS, NULL);
1172         
1173         job = g_object_new (EV_TYPE_JOB_FIND, NULL);
1174
1175         EV_JOB (job)->document = g_object_ref (document);
1176         job->start_page = start_page;
1177         job->current_page = start_page;
1178         job->n_pages = n_pages;
1179         job->pages = g_new0 (GList *, n_pages);
1180         job->text = g_strdup (text);
1181         job->case_sensitive = case_sensitive;
1182         job->has_results = FALSE;
1183
1184         return EV_JOB (job);
1185 }
1186
1187 gint
1188 ev_job_find_get_n_results (EvJobFind *job,
1189                            gint       page)
1190 {
1191         return g_list_length (job->pages[page]);
1192 }
1193
1194 gdouble
1195 ev_job_find_get_progress (EvJobFind *job)
1196 {
1197         gint pages_done;
1198
1199         if (ev_job_is_finished (EV_JOB (job)))
1200                 return 1.0;
1201         
1202         if (job->current_page > job->start_page) {
1203                 pages_done = job->current_page - job->start_page + 1;
1204         } else if (job->current_page == job->start_page) {
1205                 pages_done = job->n_pages;
1206         } else {
1207                 pages_done = job->n_pages - job->start_page + job->current_page;
1208         }
1209
1210         return pages_done / (gdouble) job->n_pages;
1211 }
1212
1213 gboolean
1214 ev_job_find_has_results (EvJobFind *job)
1215 {
1216         return job->has_results;
1217 }
1218
1219 GList **
1220 ev_job_find_get_results (EvJobFind *job)
1221 {
1222         return job->pages;
1223 }
1224
1225 /* EvJobLayers */
1226 static void
1227 ev_job_layers_init (EvJobLayers *job)
1228 {
1229         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1230 }
1231
1232 static void
1233 ev_job_layers_dispose (GObject *object)
1234 {
1235         EvJobLayers *job;
1236
1237         ev_debug_message (DEBUG_JOBS, NULL);
1238         
1239         job = EV_JOB_LAYERS (object);
1240
1241         if (job->model) {
1242                 g_object_unref (job->model);
1243                 job->model = NULL;
1244         }
1245
1246         (* G_OBJECT_CLASS (ev_job_layers_parent_class)->dispose) (object);
1247 }
1248
1249 static gboolean
1250 ev_job_layers_run (EvJob *job)
1251 {
1252         EvJobLayers *job_layers = EV_JOB_LAYERS (job);
1253
1254         ev_debug_message (DEBUG_JOBS, NULL);
1255         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1256         
1257         ev_document_doc_mutex_lock ();
1258         job_layers->model = ev_document_layers_get_layers (EV_DOCUMENT_LAYERS (job->document));
1259         ev_document_doc_mutex_unlock ();
1260         
1261         ev_job_succeeded (job);
1262         
1263         return FALSE;
1264 }
1265
1266 static void
1267 ev_job_layers_class_init (EvJobLayersClass *class)
1268 {
1269         GObjectClass *oclass = G_OBJECT_CLASS (class);
1270         EvJobClass   *job_class = EV_JOB_CLASS (class);
1271
1272         oclass->dispose = ev_job_layers_dispose;
1273         job_class->run = ev_job_layers_run;
1274 }
1275
1276 EvJob *
1277 ev_job_layers_new (EvDocument *document)
1278 {
1279         EvJob *job;
1280
1281         ev_debug_message (DEBUG_JOBS, NULL);
1282
1283         job = g_object_new (EV_TYPE_JOB_LAYERS, NULL);
1284         job->document = g_object_ref (document);
1285         
1286         return job;
1287 }
1288
1289 /* EvJobExport */
1290 static void
1291 ev_job_export_init (EvJobExport *job)
1292 {
1293         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1294         job->page = -1;
1295 }
1296
1297 static void
1298 ev_job_export_dispose (GObject *object)
1299 {
1300         EvJobExport *job;
1301
1302         ev_debug_message (DEBUG_JOBS, NULL);
1303         
1304         job = EV_JOB_EXPORT (object);
1305
1306         if (job->rc) {
1307                 g_object_unref (job->rc);
1308                 job->rc = NULL;
1309         }
1310
1311         (* G_OBJECT_CLASS (ev_job_export_parent_class)->dispose) (object);
1312 }
1313
1314 static gboolean
1315 ev_job_export_run (EvJob *job)
1316 {
1317         EvJobExport *job_export = EV_JOB_EXPORT (job);
1318         EvPage      *ev_page;
1319
1320         g_assert (job_export->page != -1);
1321
1322         ev_debug_message (DEBUG_JOBS, NULL);
1323         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1324         
1325         ev_document_doc_mutex_lock ();
1326         
1327         ev_page = ev_document_get_page (job->document, job_export->page);
1328         if (job_export->rc) {
1329                 job->failed = FALSE;
1330                 job->finished = FALSE;
1331                 g_clear_error (&job->error);
1332                 
1333                 ev_render_context_set_page (job_export->rc, ev_page);
1334         } else {
1335                 job_export->rc = ev_render_context_new (ev_page, 0, 1.0);
1336         }
1337         g_object_unref (ev_page);
1338         
1339         ev_file_exporter_do_page (EV_FILE_EXPORTER (job->document), job_export->rc);
1340         
1341         ev_document_doc_mutex_unlock ();
1342         
1343         ev_job_succeeded (job);
1344         
1345         return FALSE;
1346 }
1347
1348 static void
1349 ev_job_export_class_init (EvJobExportClass *class)
1350 {
1351         GObjectClass *oclass = G_OBJECT_CLASS (class);
1352         EvJobClass   *job_class = EV_JOB_CLASS (class);
1353
1354         oclass->dispose = ev_job_export_dispose;
1355         job_class->run = ev_job_export_run;
1356 }
1357
1358 EvJob *
1359 ev_job_export_new (EvDocument *document)
1360 {
1361         EvJob *job;
1362
1363         ev_debug_message (DEBUG_JOBS, NULL);
1364
1365         job = g_object_new (EV_TYPE_JOB_EXPORT, NULL);
1366         job->document = g_object_ref (document);
1367         
1368         return job;
1369 }
1370
1371 void
1372 ev_job_export_set_page (EvJobExport *job,
1373                         gint         page)
1374 {
1375         job->page = page;
1376 }
1377
1378 /* EvJobPrint */
1379 static void
1380 ev_job_print_init (EvJobPrint *job)
1381 {
1382         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1383         job->page = -1;
1384 }
1385
1386 static void
1387 ev_job_print_dispose (GObject *object)
1388 {
1389         EvJobPrint *job;
1390
1391         ev_debug_message (DEBUG_JOBS, NULL);
1392
1393         job = EV_JOB_PRINT (object);
1394
1395         if (job->cr) {
1396                 cairo_destroy (job->cr);
1397                 job->cr = NULL;
1398         }
1399
1400         (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
1401 }
1402
1403 static gboolean
1404 ev_job_print_run (EvJob *job)
1405 {
1406         EvJobPrint     *job_print = EV_JOB_PRINT (job);
1407         EvPage         *ev_page;
1408         cairo_status_t  cr_status;
1409
1410         g_assert (job_print->page != -1);
1411         g_assert (job_print->cr != NULL);
1412
1413         ev_debug_message (DEBUG_JOBS, NULL);
1414         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1415
1416         job->failed = FALSE;
1417         job->finished = FALSE;
1418         g_clear_error (&job->error);
1419
1420         ev_document_doc_mutex_lock ();
1421
1422         ev_page = ev_document_get_page (job->document, job_print->page);
1423         ev_document_print_print_page (EV_DOCUMENT_PRINT (job->document),
1424                                       ev_page, job_print->cr);
1425         g_object_unref (ev_page);
1426
1427         ev_document_doc_mutex_unlock ();
1428
1429         cr_status = cairo_status (job_print->cr);
1430         if (cr_status == CAIRO_STATUS_SUCCESS) {
1431                 ev_job_succeeded (job);
1432         } else {
1433                 ev_job_failed (job,
1434                                GTK_PRINT_ERROR,
1435                                GTK_PRINT_ERROR_GENERAL,
1436                                _("Failed to print page %d: %s"),
1437                                job_print->page,
1438                                cairo_status_to_string (cr_status));
1439         }
1440
1441         return FALSE;
1442 }
1443
1444 static void
1445 ev_job_print_class_init (EvJobPrintClass *class)
1446 {
1447         GObjectClass *oclass = G_OBJECT_CLASS (class);
1448         EvJobClass   *job_class = EV_JOB_CLASS (class);
1449
1450         oclass->dispose = ev_job_print_dispose;
1451         job_class->run = ev_job_print_run;
1452 }
1453
1454 EvJob *
1455 ev_job_print_new (EvDocument *document)
1456 {
1457         EvJob *job;
1458
1459         ev_debug_message (DEBUG_JOBS, NULL);
1460
1461         job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
1462         job->document = g_object_ref (document);
1463
1464         return job;
1465 }
1466
1467 void
1468 ev_job_print_set_page (EvJobPrint *job,
1469                        gint        page)
1470 {
1471         job->page = page;
1472 }
1473
1474 void
1475 ev_job_print_set_cairo (EvJobPrint *job,
1476                         cairo_t    *cr)
1477 {
1478         if (job->cr == cr)
1479                 return;
1480
1481         if (job->cr)
1482                 cairo_destroy (job->cr);
1483         job->cr = cr ? cairo_reference (cr) : NULL;
1484 }