X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=libview%2Fev-page-cache.c;h=882c42db0b5c289ed9cde071c76a620dfa03c71c;hb=f9c2880d31bb2f5d4411849b9207c5d26a5c616a;hp=ab468b93e2e077ca0fe25283e04ada093d49a3c1;hpb=8c149ccd2a3cced2cd0a676ad6f7b8d33fd98404;p=evince.git diff --git a/libview/ev-page-cache.c b/libview/ev-page-cache.c index ab468b93..882c42db 100644 --- a/libview/ev-page-cache.c +++ b/libview/ev-page-cache.c @@ -1,364 +1,343 @@ -#include -#include "ev-page-cache.h" -#include "ev-document-thumbnails.h" -#include "ev-page.h" -#include -#include +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2009 Carlos Garcia Campos + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ -struct _EvPageCache -{ - GObject parent; +#include - EvDocument *document; +#include "ev-jobs.h" +#include "ev-job-scheduler.h" +#include "ev-mapping.h" +#include "ev-selection.h" +#include "ev-document-links.h" +#include "ev-document-forms.h" +#include "ev-document-images.h" +#include "ev-document-annotations.h" +#include "ev-page-cache.h" - gint current_page; +typedef struct _EvPageCacheData { + EvJob *job; + gboolean done : 1; - gboolean dual_even_left; + GList *link_mapping; + GList *image_mapping; + GList *form_field_mapping; + GList *annot_mapping; + GdkRegion *text_mapping; +} EvPageCacheData; - double* height_to_page; - double* dual_height_to_page; +struct _EvPageCache { + GObject parent; - int rotation; + EvDocument *document; + EvPageCacheData *page_list; + gint n_pages; + EvJobPageDataFlags flags; }; -struct _EvPageCacheClass -{ +struct _EvPageCacheClass { GObjectClass parent_class; - - void (* page_changed) (EvPageCache *page_cache, gint page); - void (* history_changed) (EvPageCache *page_cache, gint page); }; -enum -{ - PAGE_CHANGED, - HISTORY_CHANGED, - N_SIGNALS, -}; - -static guint signals[N_SIGNALS] = {0, }; - -static void ev_page_cache_init (EvPageCache *page_cache); -static void ev_page_cache_class_init (EvPageCacheClass *page_cache); -static void ev_page_cache_finalize (GObject *object); +static void job_page_data_finished_cb (EvJob *job, + EvPageCache *cache); G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT) static void -ev_page_cache_init (EvPageCache *page_cache) +ev_page_cache_data_free (EvPageCacheData *data) { - page_cache->current_page = -1; -} + if (data->job) { + g_object_unref (data->job); + data->job = NULL; + } -static void -ev_page_cache_class_init (EvPageCacheClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - - object_class->finalize = ev_page_cache_finalize; - - signals [PAGE_CHANGED] = - g_signal_new ("page-changed", - EV_TYPE_PAGE_CACHE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EvPageCacheClass, page_changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - signals [HISTORY_CHANGED] = - g_signal_new ("history-changed", - EV_TYPE_PAGE_CACHE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EvPageCacheClass, history_changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); + if (data->link_mapping) { + ev_mapping_list_free (data->link_mapping, g_object_unref); + data->link_mapping = NULL; + } + if (data->image_mapping) { + ev_mapping_list_free (data->image_mapping, g_object_unref); + data->image_mapping = NULL; + } + + if (data->form_field_mapping) { + ev_mapping_list_free (data->form_field_mapping, g_object_unref); + data->form_field_mapping = NULL; + } + + if (data->annot_mapping) { + ev_mapping_list_free (data->annot_mapping, g_object_unref); + data->annot_mapping = NULL; + } + + if (data->text_mapping) { + gdk_region_destroy (data->text_mapping); + data->text_mapping = NULL; + } } static void ev_page_cache_finalize (GObject *object) { - EvPageCache *page_cache = EV_PAGE_CACHE (object); + EvPageCache *cache = EV_PAGE_CACHE (object); + gint i; + + if (cache->page_list) { + for (i = 0; i < cache->n_pages; i++) { + EvPageCacheData *data; - page_cache->document = NULL; + data = &cache->page_list[i]; + + if (data->job) + g_signal_handlers_disconnect_by_func (data->job, + G_CALLBACK (job_page_data_finished_cb), + cache); + ev_page_cache_data_free (data); + } - if (page_cache->height_to_page) { - g_free (page_cache->height_to_page); - page_cache->height_to_page = NULL; + g_free (cache->page_list); + cache->page_list = NULL; + cache->n_pages = 0; } - if (page_cache->dual_height_to_page) { - g_free (page_cache->dual_height_to_page); - page_cache->dual_height_to_page = NULL; + if (cache->document) { + g_object_unref (cache->document); + cache->document = NULL; } G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object); } static void -build_height_to_page (EvPageCache *page_cache) +ev_page_cache_init (EvPageCache *cache) { - gboolean swap, uniform, dual_even_left; - int i; - double uniform_height, page_height, next_page_height; - double saved_height; - gdouble u_width, u_height; - gint n_pages; - - swap = (page_cache->rotation == 90 || - page_cache->rotation == 270); - - uniform = ev_document_is_page_size_uniform (page_cache->document); - n_pages = ev_document_get_n_pages (page_cache->document); - dual_even_left = (n_pages > 2); - - g_free (page_cache->height_to_page); - g_free (page_cache->dual_height_to_page); - - page_cache->height_to_page = g_new0 (double, n_pages + 1); - page_cache->dual_height_to_page = g_new0 (double, n_pages + 2); - - if (uniform) - ev_document_get_page_size (page_cache->document, 0, &u_width, &u_height); - - saved_height = 0; - for (i = 0; i <= n_pages; i++) { - if (uniform) { - uniform_height = swap ? u_width : u_height; - page_cache->height_to_page[i] = i * uniform_height; - } else { - if (i < n_pages) { - gdouble w, h; - - ev_document_get_page_size (page_cache->document, i, &w, &h); - page_height = swap ? w : h; - } else { - page_height = 0; - } - page_cache->height_to_page[i] = saved_height; - saved_height += page_height; - } - } +} - if (dual_even_left && !uniform) { - gdouble w, h; +static void +ev_page_cache_class_init (EvPageCacheClass *klass) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); - ev_document_get_page_size (page_cache->document, 0, &w, &h); - saved_height = swap ? w : h; - } else { - saved_height = 0; - } + g_object_class->finalize = ev_page_cache_finalize; +} - for (i = dual_even_left; i < n_pages + 2; i += 2) { - if (uniform) { - uniform_height = swap ? u_width : u_height; - page_cache->dual_height_to_page[i] = ((i + dual_even_left) / 2) * uniform_height; - if (i + 1 < n_pages + 2) - page_cache->dual_height_to_page[i + 1] = ((i + dual_even_left) / 2) * uniform_height; - } else { - if (i + 1 < n_pages) { - gdouble w, h; - - ev_document_get_page_size (page_cache->document, i + 1, &w, &h); - next_page_height = swap ? w : h; - } else { - next_page_height = 0; - } - - if (i < n_pages) { - gdouble w, h; - - ev_document_get_page_size (page_cache->document, i, &w, &h); - page_height = swap ? w : h; - } else { - page_height = 0; - } - - if (i + 1 < n_pages + 2) { - page_cache->dual_height_to_page[i] = saved_height; - page_cache->dual_height_to_page[i + 1] = saved_height; - saved_height += MAX(page_height, next_page_height); - } else { - page_cache->dual_height_to_page[i] = saved_height; - } - } - } +static EvJobPageDataFlags +get_flags_for_document (EvDocument *document) +{ + EvJobPageDataFlags flags = EV_PAGE_DATA_INCLUDE_NONE; + + if (EV_IS_DOCUMENT_LINKS (document)) + flags |= EV_PAGE_DATA_INCLUDE_LINKS; + if (EV_IS_DOCUMENT_IMAGES (document)) + flags |= EV_PAGE_DATA_INCLUDE_IMAGES; + if (EV_IS_DOCUMENT_FORMS (document)) + flags |= EV_PAGE_DATA_INCLUDE_FORMS; + if (EV_IS_DOCUMENT_ANNOTATIONS (document)) + flags |= EV_PAGE_DATA_INCLUDE_ANNOTS; + if (EV_IS_SELECTION (document)) + flags |= EV_PAGE_DATA_INCLUDE_TEXT; + + return flags; } -static EvPageCache * +EvPageCache * ev_page_cache_new (EvDocument *document) { - EvPageCache *page_cache; + EvPageCache *cache; - page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL); - page_cache->document = document; + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); - build_height_to_page (page_cache); + cache = EV_PAGE_CACHE (g_object_new (EV_TYPE_PAGE_CACHE, NULL)); + cache->document = g_object_ref (document); + cache->n_pages = ev_document_get_n_pages (document); + cache->flags = get_flags_for_document (document); - if (ev_document_get_n_pages (page_cache->document) > 0) - ev_page_cache_set_current_page (page_cache, 0); + if (cache->flags != EV_PAGE_DATA_INCLUDE_NONE) { + cache->page_list = g_new0 (EvPageCacheData, cache->n_pages); + } - return page_cache; + return cache; } -gint -ev_page_cache_get_current_page (EvPageCache *page_cache) +static void +job_page_data_finished_cb (EvJob *job, + EvPageCache *cache) { - g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0); - - return page_cache->current_page; + EvJobPageData *job_data = EV_JOB_PAGE_DATA (job); + EvPageCacheData *data; + + data = &cache->page_list[job_data->page]; + data->link_mapping = job_data->link_mapping; + data->image_mapping = job_data->image_mapping; + data->form_field_mapping = job_data->form_field_mapping; + data->annot_mapping = job_data->annot_mapping; + data->text_mapping = job_data->text_mapping; + data->done = TRUE; + + g_object_unref (data->job); + data->job = NULL; } void -ev_page_cache_set_current_page (EvPageCache *page_cache, - int page) +ev_page_cache_set_page_range (EvPageCache *cache, + gint start, + gint end) { - g_return_if_fail (EV_IS_PAGE_CACHE (page_cache)); + gint i; - if (page == page_cache->current_page) + if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE) return; - page_cache->current_page = page; - g_signal_emit (page_cache, signals[PAGE_CHANGED], 0, page); + for (i = start; i <= end; i++) { + EvPageCacheData *data = &cache->page_list[i]; + + if (data->done || data->job) + continue; + + data->job = ev_job_page_data_new (cache->document, i, cache->flags); + g_signal_connect (data->job, "finished", + G_CALLBACK (job_page_data_finished_cb), + cache); + ev_job_scheduler_push_job (data->job, EV_JOB_PRIORITY_NONE); + } } -void -ev_page_cache_set_current_page_history (EvPageCache *page_cache, - int page) +EvJobPageDataFlags +ev_page_cache_get_flags (EvPageCache *cache) { - if (abs (page - page_cache->current_page) > 1) - g_signal_emit (page_cache, signals [HISTORY_CHANGED], 0, page); - - ev_page_cache_set_current_page (page_cache, page); + return cache->flags; } -gboolean -ev_page_cache_set_page_label (EvPageCache *page_cache, - const gchar *page_label) +void +ev_page_cache_set_flags (EvPageCache *cache, + EvJobPageDataFlags flags) { - gint page; - - g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE); - - if (ev_document_find_page_by_label (page_cache->document, page_label, &page)) { - ev_page_cache_set_current_page (page_cache, page); - return TRUE; - } - - return FALSE; + cache->flags = flags; } -void -ev_page_cache_get_size (EvPageCache *page_cache, - gint page, - gint rotation, - gfloat scale, - gint *width, - gint *height) +GList * +ev_page_cache_get_link_mapping (EvPageCache *cache, + gint page) { - double w, h; + EvPageCacheData *data; - g_return_if_fail (EV_IS_PAGE_CACHE (page_cache)); + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); - ev_document_get_page_size (page_cache->document, page, &w, &h); + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS)) + return NULL; - w = w * scale + 0.5; - h = h * scale + 0.5; + data = &cache->page_list[page]; + if (data->done) + return data->link_mapping; - if (rotation == 0 || rotation == 180) { - if (width) *width = (int)w; - if (height) *height = (int)h; - } else { - if (width) *width = (int)h; - if (height) *height = (int)w; - } + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->link_mapping; + + return data->link_mapping; } -void -ev_page_cache_get_max_width (EvPageCache *page_cache, - gint rotation, - gfloat scale, - gint *width) +GList * +ev_page_cache_get_image_mapping (EvPageCache *cache, + gint page) { - double w, h; + EvPageCacheData *data; - g_return_if_fail (EV_IS_PAGE_CACHE (page_cache)); + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); - if (!width) - return; + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES)) + return NULL; + + data = &cache->page_list[page]; + if (data->done) + return data->image_mapping; + + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->image_mapping; - ev_document_get_max_page_size (page_cache->document, &w, &h); - *width = (rotation == 0 || rotation == 180) ? w * scale : h * scale; + return data->image_mapping; } -void -ev_page_cache_get_max_height (EvPageCache *page_cache, - gint rotation, - gfloat scale, - gint *height) +GList * +ev_page_cache_get_form_field_mapping (EvPageCache *cache, + gint page) { - double w, h; + EvPageCacheData *data; - g_return_if_fail (EV_IS_PAGE_CACHE (page_cache)); + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); - if (!height) - return; + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS)) + return NULL; - ev_document_get_max_page_size (page_cache->document, &w, &h); - *height = (rotation == 0 || rotation == 180) ? h * scale : w * scale; + data = &cache->page_list[page]; + if (data->done) + return data->form_field_mapping; + + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->form_field_mapping; + + return data->form_field_mapping; } -void -ev_page_cache_get_height_to_page (EvPageCache *page_cache, - gint page, - gint rotation, - gfloat scale, - gint *height, - gint *dual_height) +GList * +ev_page_cache_get_annot_mapping (EvPageCache *cache, + gint page) { - g_return_if_fail (EV_IS_PAGE_CACHE (page_cache)); - g_return_if_fail (page >= 0); + EvPageCacheData *data; - if (page_cache->rotation != rotation) { - page_cache->rotation = rotation; - build_height_to_page (page_cache); - } + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); - if (height) - *height = page_cache->height_to_page[page] * scale; + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS)) + return NULL; - if (dual_height) - *dual_height = page_cache->dual_height_to_page[page] * scale; -} + data = &cache->page_list[page]; + if (data->done) + return data->annot_mapping; -gboolean -ev_page_cache_get_dual_even_left (EvPageCache *page_cache) -{ - g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0); + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->annot_mapping; - return (ev_document_get_n_pages (page_cache->document) > 2); + return data->annot_mapping; } -#define PAGE_CACHE_STRING "ev-page-cache" - -EvPageCache * -ev_page_cache_get (EvDocument *document) +GdkRegion * +ev_page_cache_get_text_mapping (EvPageCache *cache, + gint page) { - EvPageCache *page_cache; + EvPageCacheData *data; - g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); - page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING); - if (page_cache == NULL) { - page_cache = ev_page_cache_new (document); - g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref); - } + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT)) + return NULL; + + data = &cache->page_list[page]; + if (data->done) + return data->text_mapping; - return page_cache; + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->text_mapping; + + return data->text_mapping; } +