1 /* this file is part of evince, a gnome document viewer
3 * Copyright (C) 2009 Carlos Garcia Campos
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.
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.
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.
24 #include "ev-job-scheduler.h"
25 #include "ev-mapping-list.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"
34 typedef struct _EvPageCacheData {
38 EvJobPageDataFlags flags;
40 EvMappingList *link_mapping;
41 EvMappingList *image_mapping;
42 EvMappingList *form_field_mapping;
43 EvMappingList *annot_mapping;
44 cairo_region_t *text_mapping;
45 EvRectangle *text_layout;
46 guint text_layout_length;
54 EvPageCacheData *page_list;
61 EvJobPageDataFlags flags;
64 struct _EvPageCacheClass {
65 GObjectClass parent_class;
68 #define EV_PAGE_DATA_FLAGS_DEFAULT ( \
69 EV_PAGE_DATA_INCLUDE_LINKS | \
70 EV_PAGE_DATA_INCLUDE_TEXT_MAPPING | \
71 EV_PAGE_DATA_INCLUDE_IMAGES | \
72 EV_PAGE_DATA_INCLUDE_FORMS | \
73 EV_PAGE_DATA_INCLUDE_ANNOTS)
76 static void job_page_data_finished_cb (EvJob *job,
78 static void job_page_data_cancelled_cb (EvJob *job,
79 EvPageCacheData *data);
81 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
84 ev_page_cache_data_free (EvPageCacheData *data)
87 g_object_unref (data->job);
91 if (data->link_mapping) {
92 ev_mapping_list_unref (data->link_mapping);
93 data->link_mapping = NULL;
96 if (data->image_mapping) {
97 ev_mapping_list_unref (data->image_mapping);
98 data->image_mapping = NULL;
101 if (data->form_field_mapping) {
102 ev_mapping_list_unref (data->form_field_mapping);
103 data->form_field_mapping = NULL;
106 if (data->annot_mapping) {
107 ev_mapping_list_unref (data->annot_mapping);
108 data->annot_mapping = NULL;
111 if (data->text_mapping) {
112 cairo_region_destroy (data->text_mapping);
113 data->text_mapping = NULL;
116 if (data->text_layout) {
117 g_free (data->text_layout);
118 data->text_layout = NULL;
119 data->text_layout_length = 0;
129 ev_page_cache_finalize (GObject *object)
131 EvPageCache *cache = EV_PAGE_CACHE (object);
134 if (cache->page_list) {
135 for (i = 0; i < cache->n_pages; i++) {
136 EvPageCacheData *data;
138 data = &cache->page_list[i];
141 g_signal_handlers_disconnect_by_func (data->job,
142 G_CALLBACK (job_page_data_finished_cb),
144 g_signal_handlers_disconnect_by_func (data->job,
145 G_CALLBACK (job_page_data_cancelled_cb),
148 ev_page_cache_data_free (data);
151 g_free (cache->page_list);
152 cache->page_list = NULL;
156 if (cache->document) {
157 g_object_unref (cache->document);
158 cache->document = NULL;
161 G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
165 ev_page_cache_init (EvPageCache *cache)
170 ev_page_cache_class_init (EvPageCacheClass *klass)
172 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
174 g_object_class->finalize = ev_page_cache_finalize;
177 static EvJobPageDataFlags
178 ev_page_cache_get_flags_for_data (EvPageCache *cache,
179 EvPageCacheData *data)
181 EvJobPageDataFlags flags = EV_PAGE_DATA_INCLUDE_NONE;
183 if (data->flags == cache->flags && !data->dirty)
186 /* Flags changed or data is dirty */
187 if (cache->flags & EV_PAGE_DATA_INCLUDE_LINKS) {
188 flags = (data->link_mapping) ?
189 flags & ~EV_PAGE_DATA_INCLUDE_LINKS :
190 flags | EV_PAGE_DATA_INCLUDE_LINKS;
193 if (cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES) {
194 flags = (data->image_mapping) ?
195 flags & ~EV_PAGE_DATA_INCLUDE_IMAGES :
196 flags | EV_PAGE_DATA_INCLUDE_IMAGES;
199 if (cache->flags & EV_PAGE_DATA_INCLUDE_FORMS) {
200 flags = (data->form_field_mapping) ?
201 flags & ~EV_PAGE_DATA_INCLUDE_FORMS :
202 flags | EV_PAGE_DATA_INCLUDE_FORMS;
205 if (cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) {
206 flags = (data->annot_mapping) ?
207 flags & ~EV_PAGE_DATA_INCLUDE_ANNOTS :
208 flags | EV_PAGE_DATA_INCLUDE_ANNOTS;
211 if (cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING) {
212 flags = (data->text_mapping) ?
213 flags & ~EV_PAGE_DATA_INCLUDE_TEXT_MAPPING :
214 flags | EV_PAGE_DATA_INCLUDE_TEXT_MAPPING;
217 if (cache->flags & EV_PAGE_DATA_INCLUDE_TEXT) {
218 flags = (data->text) ?
219 flags & ~EV_PAGE_DATA_INCLUDE_TEXT :
220 flags | EV_PAGE_DATA_INCLUDE_TEXT;
223 if (cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT) {
224 flags = (data->text_layout_length > 0) ?
225 flags & ~EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT :
226 flags | EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT;
233 ev_page_cache_new (EvDocument *document)
237 g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
239 cache = EV_PAGE_CACHE (g_object_new (EV_TYPE_PAGE_CACHE, NULL));
240 cache->document = g_object_ref (document);
241 cache->n_pages = ev_document_get_n_pages (document);
242 cache->flags = EV_PAGE_DATA_FLAGS_DEFAULT;
243 cache->page_list = g_new0 (EvPageCacheData, cache->n_pages);
249 job_page_data_finished_cb (EvJob *job,
252 EvJobPageData *job_data = EV_JOB_PAGE_DATA (job);
253 EvPageCacheData *data;
255 data = &cache->page_list[job_data->page];
257 if (job_data->flags & EV_PAGE_DATA_INCLUDE_LINKS)
258 data->link_mapping = job_data->link_mapping;
259 if (job_data->flags & EV_PAGE_DATA_INCLUDE_IMAGES)
260 data->image_mapping = job_data->image_mapping;
261 if (job_data->flags & EV_PAGE_DATA_INCLUDE_FORMS)
262 data->form_field_mapping = job_data->form_field_mapping;
263 if (job_data->flags & EV_PAGE_DATA_INCLUDE_ANNOTS)
264 data->annot_mapping = job_data->annot_mapping;
265 if (job_data->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING)
266 data->text_mapping = job_data->text_mapping;
267 if (job_data->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT) {
268 data->text_layout = job_data->text_layout;
269 data->text_layout_length = job_data->text_layout_length;
271 if (job_data->flags & EV_PAGE_DATA_INCLUDE_TEXT)
272 data->text = job_data->text;
276 g_object_unref (data->job);
281 job_page_data_cancelled_cb (EvJob *job,
282 EvPageCacheData *data)
284 g_object_unref (data->job);
289 ev_page_cache_set_page_range (EvPageCache *cache,
295 if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE)
298 cache->start_page = start;
299 cache->end_page = end;
301 for (i = start; i <= end; i++) {
302 EvPageCacheData *data = &cache->page_list[i];
303 EvJobPageDataFlags flags;
305 if (data->flags == cache->flags && !data->dirty && (data->done || data->job))
309 ev_job_cancel (data->job);
311 flags = ev_page_cache_get_flags_for_data (cache, data);
313 data->flags = cache->flags;
314 data->job = ev_job_page_data_new (cache->document, i, flags);
315 g_signal_connect (data->job, "finished",
316 G_CALLBACK (job_page_data_finished_cb),
318 g_signal_connect (data->job, "cancelled",
319 G_CALLBACK (job_page_data_cancelled_cb),
321 ev_job_scheduler_push_job (data->job, EV_JOB_PRIORITY_NONE);
326 ev_page_cache_get_flags (EvPageCache *cache)
332 ev_page_cache_set_flags (EvPageCache *cache,
333 EvJobPageDataFlags flags)
335 if (cache->flags == flags)
338 cache->flags = flags;
340 /* Update the current range for new flags */
341 ev_page_cache_set_page_range (cache, cache->start_page, cache->end_page);
345 ev_page_cache_mark_dirty (EvPageCache *cache,
348 EvPageCacheData *data;
350 g_return_if_fail (EV_IS_PAGE_CACHE (cache));
352 data = &cache->page_list[page];
355 /* Update the current range */
356 ev_page_cache_set_page_range (cache, cache->start_page, cache->end_page);
360 ev_page_cache_get_link_mapping (EvPageCache *cache,
363 EvPageCacheData *data;
365 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
366 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
368 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS))
371 data = &cache->page_list[page];
373 return data->link_mapping;
376 return EV_JOB_PAGE_DATA (data->job)->link_mapping;
378 return data->link_mapping;
382 ev_page_cache_get_image_mapping (EvPageCache *cache,
385 EvPageCacheData *data;
387 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
388 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
390 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES))
393 data = &cache->page_list[page];
395 return data->image_mapping;
398 return EV_JOB_PAGE_DATA (data->job)->image_mapping;
400 return data->image_mapping;
404 ev_page_cache_get_form_field_mapping (EvPageCache *cache,
407 EvPageCacheData *data;
409 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
410 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
412 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS))
415 data = &cache->page_list[page];
417 return data->form_field_mapping;
420 return EV_JOB_PAGE_DATA (data->job)->form_field_mapping;
422 return data->form_field_mapping;
426 ev_page_cache_get_annot_mapping (EvPageCache *cache,
429 EvPageCacheData *data;
431 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
432 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
434 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS))
437 data = &cache->page_list[page];
439 return data->annot_mapping;
442 return EV_JOB_PAGE_DATA (data->job)->annot_mapping;
444 return data->annot_mapping;
448 ev_page_cache_get_text_mapping (EvPageCache *cache,
451 EvPageCacheData *data;
453 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
454 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
456 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING))
459 data = &cache->page_list[page];
461 return data->text_mapping;
464 return EV_JOB_PAGE_DATA (data->job)->text_mapping;
466 return data->text_mapping;
470 ev_page_cache_get_text (EvPageCache *cache,
473 EvPageCacheData *data;
475 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
476 g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
478 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT))
481 data = &cache->page_list[page];
486 return EV_JOB_PAGE_DATA (data->job)->text;
492 ev_page_cache_get_text_layout (EvPageCache *cache,
497 EvPageCacheData *data;
499 g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), FALSE);
500 g_return_val_if_fail (page >= 0 && page < cache->n_pages, FALSE);
502 if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT))
505 data = &cache->page_list[page];
507 *areas = data->text_layout;
508 *n_areas = data->text_layout_length;
514 *areas = EV_JOB_PAGE_DATA (data->job)->text_layout;
515 *n_areas = EV_JOB_PAGE_DATA (data->job)->text_layout_length;