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