]> www.fi.muni.cz Git - evince.git/blob - libview/ev-page-cache.c
[presentation] Fix fade animations
[evince.git] / libview / ev-page-cache.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2009 Carlos Garcia Campos
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21
22 #include "ev-jobs.h"
23 #include "ev-job-scheduler.h"
24 #include "ev-mapping.h"
25 #include "ev-selection.h"
26 #include "ev-document-links.h"
27 #include "ev-document-forms.h"
28 #include "ev-document-images.h"
29 #include "ev-document-annotations.h"
30 #include "ev-page-cache.h"
31
32 typedef struct _EvPageCacheData {
33         EvJob     *job;
34         gboolean   done : 1;
35
36         GList     *link_mapping;
37         GList     *image_mapping;
38         GList     *form_field_mapping;
39         GList     *annot_mapping;
40         GdkRegion *text_mapping;
41 } EvPageCacheData;
42
43 struct _EvPageCache {
44         GObject parent;
45
46         EvDocument        *document;
47         EvPageCacheData   *page_list;
48         gint               n_pages;
49         EvJobPageDataFlags flags;
50 };
51
52 struct _EvPageCacheClass {
53         GObjectClass parent_class;
54 };
55
56 static void job_page_data_finished_cb (EvJob       *job,
57                                        EvPageCache *cache);
58
59 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
60
61 static void
62 ev_page_cache_data_free (EvPageCacheData *data)
63 {
64         if (data->job) {
65                 g_object_unref (data->job);
66                 data->job = NULL;
67         }
68
69         if (data->link_mapping) {
70                 ev_mapping_list_free (data->link_mapping, g_object_unref);
71                 data->link_mapping = NULL;
72         }
73
74         if (data->image_mapping) {
75                 ev_mapping_list_free (data->image_mapping, g_object_unref);
76                 data->image_mapping = NULL;
77         }
78
79         if (data->form_field_mapping) {
80                 ev_mapping_list_free (data->form_field_mapping, g_object_unref);
81                 data->form_field_mapping = NULL;
82         }
83
84         if (data->annot_mapping) {
85                 ev_mapping_list_free (data->annot_mapping, g_object_unref);
86                 data->annot_mapping = NULL;
87         }
88
89         if (data->text_mapping) {
90                 gdk_region_destroy (data->text_mapping);
91                 data->text_mapping = NULL;
92         }
93 }
94
95 static void
96 ev_page_cache_finalize (GObject *object)
97 {
98         EvPageCache *cache = EV_PAGE_CACHE (object);
99         gint         i;
100
101         if (cache->page_list) {
102                 for (i = 0; i < cache->n_pages; i++) {
103                         EvPageCacheData *data;
104
105                         data = &cache->page_list[i];
106
107                         if (data->job)
108                                 g_signal_handlers_disconnect_by_func (data->job,
109                                                                       G_CALLBACK (job_page_data_finished_cb),
110                                                                       cache);
111                         ev_page_cache_data_free (data);
112                 }
113
114                 g_free (cache->page_list);
115                 cache->page_list = NULL;
116                 cache->n_pages = 0;
117         }
118
119         if (cache->document) {
120                 g_object_unref (cache->document);
121                 cache->document = NULL;
122         }
123
124         G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
125 }
126
127 static void
128 ev_page_cache_init (EvPageCache *cache)
129 {
130 }
131
132 static void
133 ev_page_cache_class_init (EvPageCacheClass *klass)
134 {
135         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
136
137         g_object_class->finalize = ev_page_cache_finalize;
138 }
139
140 static EvJobPageDataFlags
141 get_flags_for_document (EvDocument *document)
142 {
143         EvJobPageDataFlags flags = EV_PAGE_DATA_INCLUDE_NONE;
144
145         if (EV_IS_DOCUMENT_LINKS (document))
146                 flags |= EV_PAGE_DATA_INCLUDE_LINKS;
147         if (EV_IS_DOCUMENT_IMAGES (document))
148                 flags |= EV_PAGE_DATA_INCLUDE_IMAGES;
149         if (EV_IS_DOCUMENT_FORMS (document))
150                 flags |= EV_PAGE_DATA_INCLUDE_FORMS;
151         if (EV_IS_DOCUMENT_ANNOTATIONS (document))
152                 flags |= EV_PAGE_DATA_INCLUDE_ANNOTS;
153         if (EV_IS_SELECTION (document))
154                 flags |= EV_PAGE_DATA_INCLUDE_TEXT;
155
156         return flags;
157 }
158
159 EvPageCache *
160 ev_page_cache_new (EvDocument *document)
161 {
162         EvPageCache *cache;
163
164         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
165
166         cache = EV_PAGE_CACHE (g_object_new (EV_TYPE_PAGE_CACHE, NULL));
167         cache->document = g_object_ref (document);
168         cache->n_pages = ev_document_get_n_pages (document);
169         cache->flags = get_flags_for_document (document);
170
171         if (cache->flags != EV_PAGE_DATA_INCLUDE_NONE) {
172                 cache->page_list = g_new0 (EvPageCacheData, cache->n_pages);
173         }
174
175         return cache;
176 }
177
178 static void
179 job_page_data_finished_cb (EvJob       *job,
180                            EvPageCache *cache)
181 {
182         EvJobPageData   *job_data = EV_JOB_PAGE_DATA (job);
183         EvPageCacheData *data;
184
185         data = &cache->page_list[job_data->page];
186         data->link_mapping = job_data->link_mapping;
187         data->image_mapping = job_data->image_mapping;
188         data->form_field_mapping = job_data->form_field_mapping;
189         data->annot_mapping = job_data->annot_mapping;
190         data->text_mapping = job_data->text_mapping;
191         data->done = TRUE;
192
193         g_object_unref (data->job);
194         data->job = NULL;
195 }
196
197 void
198 ev_page_cache_set_page_range (EvPageCache *cache,
199                               gint         start,
200                               gint         end)
201 {
202         gint i;
203
204         if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE)
205                 return;
206
207         for (i = start; i <= end; i++) {
208                 EvPageCacheData *data = &cache->page_list[i];
209
210                 if (data->done || data->job)
211                         continue;
212
213                 data->job = ev_job_page_data_new (cache->document, i, cache->flags);
214                 g_signal_connect (data->job, "finished",
215                                   G_CALLBACK (job_page_data_finished_cb),
216                                   cache);
217                 ev_job_scheduler_push_job (data->job, EV_JOB_PRIORITY_NONE);
218         }
219 }
220
221 EvJobPageDataFlags
222 ev_page_cache_get_flags (EvPageCache *cache)
223 {
224         return cache->flags;
225 }
226
227 void
228 ev_page_cache_set_flags (EvPageCache       *cache,
229                          EvJobPageDataFlags flags)
230 {
231         cache->flags = flags;
232 }
233
234 GList *
235 ev_page_cache_get_link_mapping (EvPageCache *cache,
236                                 gint         page)
237 {
238         EvPageCacheData *data;
239
240         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
241         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
242
243         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS))
244                 return NULL;
245
246         data = &cache->page_list[page];
247         if (data->done)
248                 return data->link_mapping;
249
250         if (data->job)
251                 return EV_JOB_PAGE_DATA (data->job)->link_mapping;
252
253         return data->link_mapping;
254 }
255
256 GList *
257 ev_page_cache_get_image_mapping (EvPageCache *cache,
258                                  gint         page)
259 {
260         EvPageCacheData *data;
261
262         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
263         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
264
265         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES))
266                 return NULL;
267
268         data = &cache->page_list[page];
269         if (data->done)
270                 return data->image_mapping;
271
272         if (data->job)
273                 return EV_JOB_PAGE_DATA (data->job)->image_mapping;
274
275         return data->image_mapping;
276 }
277
278 GList *
279 ev_page_cache_get_form_field_mapping (EvPageCache *cache,
280                                       gint         page)
281 {
282         EvPageCacheData *data;
283
284         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
285         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
286
287         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS))
288                 return NULL;
289
290         data = &cache->page_list[page];
291         if (data->done)
292                 return data->form_field_mapping;
293
294         if (data->job)
295                 return EV_JOB_PAGE_DATA (data->job)->form_field_mapping;
296
297         return data->form_field_mapping;
298 }
299
300 GList *
301 ev_page_cache_get_annot_mapping (EvPageCache *cache,
302                                  gint         page)
303 {
304         EvPageCacheData *data;
305
306         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
307         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
308
309         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS))
310                 return NULL;
311
312         data = &cache->page_list[page];
313         if (data->done)
314                 return data->annot_mapping;
315
316         if (data->job)
317                 return EV_JOB_PAGE_DATA (data->job)->annot_mapping;
318
319         return data->annot_mapping;
320 }
321
322 GdkRegion *
323 ev_page_cache_get_text_mapping (EvPageCache *cache,
324                                 gint         page)
325 {
326         EvPageCacheData *data;
327
328         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
329         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
330
331         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT))
332                 return NULL;
333
334         data = &cache->page_list[page];
335         if (data->done)
336                 return data->text_mapping;
337
338         if (data->job)
339                 return EV_JOB_PAGE_DATA (data->job)->text_mapping;
340
341         return data->text_mapping;
342 }
343