~ubuntu-branches/ubuntu/precise/evince/precise-updates

« back to all changes in this revision

Viewing changes to libview/ev-jobs.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2009-01-19 10:39:43 UTC
  • mto: (1.6.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 70.
  • Revision ID: james.westby@ubuntu.com-20090119103943-dhe56g9rmuq7khys
Tags: upstream-2.25.5
ImportĀ upstreamĀ versionĀ 2.25.5

Show diffs side-by-side

added added

removed removed

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