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