]> www.fi.muni.cz Git - evince.git/blob - libview/ev-page-cache.c
Switch to GTK+ 3
[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 <glib.h>
23 #include "ev-jobs.h"
24 #include "ev-job-scheduler.h"
25 #include "ev-mapping.h"
26 #include "ev-selection.h"
27 #include "ev-document-links.h"
28 #include "ev-document-forms.h"
29 #include "ev-document-images.h"
30 #include "ev-document-annotations.h"
31 #include "ev-document-text.h"
32 #include "ev-page-cache.h"
33
34 typedef struct _EvPageCacheData {
35         EvJob          *job;
36         gboolean        done : 1;
37
38         GList          *link_mapping;
39         GList          *image_mapping;
40         GList          *form_field_mapping;
41         GList          *annot_mapping;
42         cairo_region_t *text_mapping;
43         EvRectangle    *text_layout;
44         guint           text_layout_length;
45         gchar          *text;
46 } EvPageCacheData;
47
48 struct _EvPageCache {
49         GObject parent;
50
51         EvDocument        *document;
52         EvPageCacheData   *page_list;
53         gint               n_pages;
54         EvJobPageDataFlags flags;
55 };
56
57 struct _EvPageCacheClass {
58         GObjectClass parent_class;
59 };
60
61 static void job_page_data_finished_cb (EvJob       *job,
62                                        EvPageCache *cache);
63
64 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
65
66 static void
67 ev_page_cache_data_free (EvPageCacheData *data)
68 {
69         if (data->job) {
70                 g_object_unref (data->job);
71                 data->job = NULL;
72         }
73
74         if (data->link_mapping) {
75                 ev_mapping_list_free (data->link_mapping, g_object_unref);
76                 data->link_mapping = NULL;
77         }
78
79         if (data->image_mapping) {
80                 ev_mapping_list_free (data->image_mapping, g_object_unref);
81                 data->image_mapping = NULL;
82         }
83
84         if (data->form_field_mapping) {
85                 ev_mapping_list_free (data->form_field_mapping, g_object_unref);
86                 data->form_field_mapping = NULL;
87         }
88
89         if (data->annot_mapping) {
90                 ev_mapping_list_free (data->annot_mapping, g_object_unref);
91                 data->annot_mapping = NULL;
92         }
93
94         if (data->text_mapping) {
95                 cairo_region_destroy (data->text_mapping);
96                 data->text_mapping = NULL;
97         }
98
99         if (data->text_layout) {
100                 g_free (data->text_layout);
101                 data->text_layout = NULL;
102                 data->text_layout_length = 0;
103         }
104
105         if (data->text) {
106                 g_free (data->text);
107                 data->text = NULL;
108         }
109 }
110
111 static void
112 ev_page_cache_finalize (GObject *object)
113 {
114         EvPageCache *cache = EV_PAGE_CACHE (object);
115         gint         i;
116
117         if (cache->page_list) {
118                 for (i = 0; i < cache->n_pages; i++) {
119                         EvPageCacheData *data;
120
121                         data = &cache->page_list[i];
122
123                         if (data->job)
124                                 g_signal_handlers_disconnect_by_func (data->job,
125                                                                       G_CALLBACK (job_page_data_finished_cb),
126                                                                       cache);
127                         ev_page_cache_data_free (data);
128                 }
129
130                 g_free (cache->page_list);
131                 cache->page_list = NULL;
132                 cache->n_pages = 0;
133         }
134
135         if (cache->document) {
136                 g_object_unref (cache->document);
137                 cache->document = NULL;
138         }
139
140         G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
141 }
142
143 static void
144 ev_page_cache_init (EvPageCache *cache)
145 {
146 }
147
148 static void
149 ev_page_cache_class_init (EvPageCacheClass *klass)
150 {
151         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
152
153         g_object_class->finalize = ev_page_cache_finalize;
154 }
155
156 static EvJobPageDataFlags
157 get_flags_for_document (EvDocument *document)
158 {
159         EvJobPageDataFlags flags = EV_PAGE_DATA_INCLUDE_NONE;
160
161         if (EV_IS_DOCUMENT_LINKS (document))
162                 flags |= EV_PAGE_DATA_INCLUDE_LINKS;
163         if (EV_IS_DOCUMENT_IMAGES (document))
164                 flags |= EV_PAGE_DATA_INCLUDE_IMAGES;
165         if (EV_IS_DOCUMENT_FORMS (document))
166                 flags |= EV_PAGE_DATA_INCLUDE_FORMS;
167         if (EV_IS_DOCUMENT_ANNOTATIONS (document))
168                 flags |= EV_PAGE_DATA_INCLUDE_ANNOTS;
169         if (EV_IS_SELECTION (document) && EV_IS_DOCUMENT_TEXT (document))
170                 flags |= EV_PAGE_DATA_INCLUDE_TEXT_MAPPING;
171         if (EV_IS_DOCUMENT_TEXT (document))
172                 flags |= EV_PAGE_DATA_INCLUDE_TEXT | EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT;
173
174         return flags;
175 }
176
177 EvPageCache *
178 ev_page_cache_new (EvDocument *document)
179 {
180         EvPageCache *cache;
181
182         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
183
184         cache = EV_PAGE_CACHE (g_object_new (EV_TYPE_PAGE_CACHE, NULL));
185         cache->document = g_object_ref (document);
186         cache->n_pages = ev_document_get_n_pages (document);
187         cache->flags = get_flags_for_document (document);
188
189         if (cache->flags != EV_PAGE_DATA_INCLUDE_NONE) {
190                 cache->page_list = g_new0 (EvPageCacheData, cache->n_pages);
191         }
192
193         return cache;
194 }
195
196 static void
197 job_page_data_finished_cb (EvJob       *job,
198                            EvPageCache *cache)
199 {
200         EvJobPageData   *job_data = EV_JOB_PAGE_DATA (job);
201         EvPageCacheData *data;
202
203         data = &cache->page_list[job_data->page];
204         data->link_mapping = job_data->link_mapping;
205         data->image_mapping = job_data->image_mapping;
206         data->form_field_mapping = job_data->form_field_mapping;
207         data->annot_mapping = job_data->annot_mapping;
208         data->text_mapping = job_data->text_mapping;
209         data->text_layout = job_data->text_layout;
210         data->text_layout_length = job_data->text_layout_length;
211         data->text = job_data->text;
212         data->done = TRUE;
213
214         g_object_unref (data->job);
215         data->job = NULL;
216 }
217
218 void
219 ev_page_cache_set_page_range (EvPageCache *cache,
220                               gint         start,
221                               gint         end)
222 {
223         gint i;
224
225         if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE)
226                 return;
227
228         for (i = start; i <= end; i++) {
229                 EvPageCacheData *data = &cache->page_list[i];
230
231                 if (data->done || data->job)
232                         continue;
233
234                 data->job = ev_job_page_data_new (cache->document, i, cache->flags);
235                 g_signal_connect (data->job, "finished",
236                                   G_CALLBACK (job_page_data_finished_cb),
237                                   cache);
238                 ev_job_scheduler_push_job (data->job, EV_JOB_PRIORITY_NONE);
239         }
240 }
241
242 EvJobPageDataFlags
243 ev_page_cache_get_flags (EvPageCache *cache)
244 {
245         return cache->flags;
246 }
247
248 void
249 ev_page_cache_set_flags (EvPageCache       *cache,
250                          EvJobPageDataFlags flags)
251 {
252         cache->flags = flags;
253 }
254
255 GList *
256 ev_page_cache_get_link_mapping (EvPageCache *cache,
257                                 gint         page)
258 {
259         EvPageCacheData *data;
260
261         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
262         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
263
264         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS))
265                 return NULL;
266
267         data = &cache->page_list[page];
268         if (data->done)
269                 return data->link_mapping;
270
271         if (data->job)
272                 return EV_JOB_PAGE_DATA (data->job)->link_mapping;
273
274         return data->link_mapping;
275 }
276
277 GList *
278 ev_page_cache_get_image_mapping (EvPageCache *cache,
279                                  gint         page)
280 {
281         EvPageCacheData *data;
282
283         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
284         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
285
286         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES))
287                 return NULL;
288
289         data = &cache->page_list[page];
290         if (data->done)
291                 return data->image_mapping;
292
293         if (data->job)
294                 return EV_JOB_PAGE_DATA (data->job)->image_mapping;
295
296         return data->image_mapping;
297 }
298
299 GList *
300 ev_page_cache_get_form_field_mapping (EvPageCache *cache,
301                                       gint         page)
302 {
303         EvPageCacheData *data;
304
305         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
306         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
307
308         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS))
309                 return NULL;
310
311         data = &cache->page_list[page];
312         if (data->done)
313                 return data->form_field_mapping;
314
315         if (data->job)
316                 return EV_JOB_PAGE_DATA (data->job)->form_field_mapping;
317
318         return data->form_field_mapping;
319 }
320
321 GList *
322 ev_page_cache_get_annot_mapping (EvPageCache *cache,
323                                  gint         page)
324 {
325         EvPageCacheData *data;
326
327         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
328         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
329
330         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS))
331                 return NULL;
332
333         data = &cache->page_list[page];
334         if (data->done)
335                 return data->annot_mapping;
336
337         if (data->job)
338                 return EV_JOB_PAGE_DATA (data->job)->annot_mapping;
339
340         return data->annot_mapping;
341 }
342
343 cairo_region_t *
344 ev_page_cache_get_text_mapping (EvPageCache *cache,
345                                 gint         page)
346 {
347         EvPageCacheData *data;
348
349         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
350         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
351
352         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING))
353                 return NULL;
354
355         data = &cache->page_list[page];
356         if (data->done)
357                 return data->text_mapping;
358
359         if (data->job)
360                 return EV_JOB_PAGE_DATA (data->job)->text_mapping;
361
362         return data->text_mapping;
363 }
364
365 const gchar *
366 ev_page_cache_get_text (EvPageCache *cache,
367                              gint         page)
368 {
369         EvPageCacheData *data;
370
371         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
372         g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
373
374         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT))
375                 return NULL;
376
377         data = &cache->page_list[page];
378         if (data->done)
379                 return data->text;
380
381         if (data->job)
382                 return EV_JOB_PAGE_DATA (data->job)->text;
383
384         return data->text;
385 }
386
387 gboolean
388 ev_page_cache_get_text_layout (EvPageCache  *cache,
389                                gint          page,
390                                EvRectangle **areas,
391                                guint        *n_areas)
392 {
393         EvPageCacheData *data;
394
395         g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), FALSE);
396         g_return_val_if_fail (page >= 0 && page < cache->n_pages, FALSE);
397
398         if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT))
399                 return FALSE;
400
401         data = &cache->page_list[page];
402         if (data->done) {
403                 *areas = data->text_layout;
404                 *n_areas = data->text_layout_length;
405
406                 return TRUE;
407         }
408
409         if (data->job) {
410                 *areas = EV_JOB_PAGE_DATA (data->job)->text_layout;
411                 *n_areas = EV_JOB_PAGE_DATA (data->job)->text_layout_length;
412
413                 return TRUE;
414         }
415
416         return FALSE;
417 }