From 3a8589a7c5e0394df456074048845cddd04bc43d Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Tue, 8 Dec 2009 18:23:50 +0100 Subject: [PATCH] [libview] Split EvPixbufCache into dynamic and static data Dynamic page data (page surfaces and selections) that depend on current scale/rotation, keep in EvPixbufCache with the current cache approach. Static page data (links, annots, images, text and forms) that don't depend on current scale/rotation, have been moved to EvPageCache and they are never removed from the cache. Fixes bgo#602405. --- help/reference/libview/libevview.types | 2 +- libview/Makefile.am | 2 + libview/ev-jobs.c | 154 +++++------ libview/ev-jobs.h | 68 +++-- libview/ev-page-cache.c | 330 ++++++++++++++++++++++++ libview/ev-page-cache.h | 59 +++++ libview/ev-pixbuf-cache.c | 341 ++++--------------------- libview/ev-pixbuf-cache.h | 10 - libview/ev-view-private.h | 2 + libview/ev-view.c | 56 ++-- 10 files changed, 612 insertions(+), 412 deletions(-) create mode 100644 libview/ev-page-cache.c create mode 100644 libview/ev-page-cache.h diff --git a/help/reference/libview/libevview.types b/help/reference/libview/libevview.types index c98d8702..003f08cc 100644 --- a/help/reference/libview/libevview.types +++ b/help/reference/libview/libevview.types @@ -13,7 +13,7 @@ ev_job_layers_get_type ev_job_export_get_type ev_view_get_type ev_job_run_mode_get_type -ev_render_flags_get_type +ev_job_page_data_flags_get_type ev_job_priority_get_type ev_sizing_mode_get_type ev_view_selection_mode_get_type diff --git a/libview/Makefile.am b/libview/Makefile.am index ef38f995..03b8d6d0 100644 --- a/libview/Makefile.am +++ b/libview/Makefile.am @@ -2,6 +2,7 @@ lib_LTLIBRARIES = libevview.la NOINST_H_FILES = \ ev-annotation-window.h \ + ev-page-cache.h \ ev-pixbuf-cache.h \ ev-timeline.h \ ev-transition-animation.h \ @@ -25,6 +26,7 @@ libevview_la_SOURCES = \ ev-document-model.c \ ev-jobs.c \ ev-job-scheduler.c \ + ev-page-cache.c \ ev-pixbuf-cache.c \ ev-stock-icons.c \ ev-timeline.c \ diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c index 620ea667..d13c06b2 100644 --- a/libview/ev-jobs.c +++ b/libview/ev-jobs.c @@ -51,6 +51,8 @@ static void ev_job_attachments_init (EvJobAttachments *job); static void ev_job_attachments_class_init (EvJobAttachmentsClass *class); static void ev_job_render_init (EvJobRender *job); static void ev_job_render_class_init (EvJobRenderClass *class); +static void ev_job_page_data_init (EvJobPageData *job); +static void ev_job_page_data_class_init (EvJobPageDataClass *class); static void ev_job_thumbnail_init (EvJobThumbnail *job); static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class); static void ev_job_load_init (EvJobLoad *job); @@ -72,11 +74,6 @@ enum { LAST_SIGNAL }; -enum { - PAGE_READY, - RENDER_LAST_SIGNAL -}; - enum { FONTS_UPDATED, FONTS_LAST_SIGNAL @@ -88,7 +85,6 @@ enum { }; static guint job_signals[LAST_SIGNAL] = { 0 }; -static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 }; static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 }; static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 }; @@ -96,6 +92,7 @@ G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT) G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB) +G_DEFINE_TYPE (EvJobPageData, ev_job_page_data, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB) @@ -475,33 +472,6 @@ ev_job_render_dispose (GObject *object) (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object); } -static gboolean -notify_page_ready (EvJobRender *job) -{ - ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job); - ev_profiler_stop (EV_PROFILE_JOBS, "Rendering page %d", job->ev_page->index); - - if (EV_JOB (job)->cancelled) { - ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit page_ready", EV_GET_TYPE_NAME (job), job); - } else { - g_signal_emit (job, job_render_signals[PAGE_READY], 0); - } - - return FALSE; -} - -static void -ev_job_render_page_ready (EvJobRender *job) -{ - ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job); - - job->page_ready = TRUE; - g_idle_add_full (G_PRIORITY_HIGH_IDLE, - (GSourceFunc)notify_page_ready, - g_object_ref (job), - (GDestroyNotify)g_object_unref); -} - static gboolean ev_job_render_run (EvJob *job) { @@ -531,8 +501,8 @@ ev_job_render_run (EvJob *job) return FALSE; } - - if ((job_render->flags & EV_RENDER_INCLUDE_SELECTION) && EV_IS_SELECTION (job->document)) { + + if (job_render->include_selection && EV_IS_SELECTION (job->document)) { ev_selection_render_selection (EV_SELECTION (job->document), rc, &(job_render->selection), @@ -547,29 +517,9 @@ ev_job_render_run (EvJob *job) &(job_render->selection_points)); } - ev_job_render_page_ready (job_render); - - ev_document_fc_mutex_unlock (); - - if ((job_render->flags & EV_RENDER_INCLUDE_TEXT) && EV_IS_SELECTION (job->document)) - job_render->text_mapping = - ev_selection_get_selection_map (EV_SELECTION (job->document), job_render->ev_page); - if ((job_render->flags & EV_RENDER_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document)) - job_render->link_mapping = - ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_render->page); - if ((job_render->flags & EV_RENDER_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document)) - job_render->form_field_mapping = - ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document), - job_render->ev_page); - if ((job_render->flags & EV_RENDER_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document)) - job_render->image_mapping = - ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document), - job_render->page); - if ((job_render->flags & EV_RENDER_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document)) - job_render->annots_mapping = - ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document), - job_render->ev_page); g_object_unref (rc); + + ev_document_fc_mutex_unlock (); ev_document_doc_mutex_unlock (); ev_job_succeeded (job); @@ -583,15 +533,6 @@ ev_job_render_class_init (EvJobRenderClass *class) GObjectClass *oclass = G_OBJECT_CLASS (class); EvJobClass *job_class = EV_JOB_CLASS (class); - job_render_signals [PAGE_READY] = - g_signal_new ("page-ready", - EV_TYPE_JOB_RENDER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EvJobRenderClass, page_ready), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - oclass->dispose = ev_job_render_dispose; job_class->run = ev_job_render_run; } @@ -600,10 +541,9 @@ EvJob * ev_job_render_new (EvDocument *document, gint page, gint rotation, - gdouble scale, + gdouble scale, gint width, - gint height, - EvRenderFlags flags) + gint height) { EvJobRender *job; @@ -617,7 +557,6 @@ ev_job_render_new (EvDocument *document, job->scale = scale; job->target_width = width; job->target_height = height; - job->flags = flags; return EV_JOB (job); } @@ -629,14 +568,85 @@ ev_job_render_set_selection_info (EvJobRender *job, GdkColor *text, GdkColor *base) { - job->flags |= EV_RENDER_INCLUDE_SELECTION; - + job->include_selection = TRUE; + job->selection_points = *selection_points; job->selection_style = selection_style; job->text = *text; job->base = *base; } +/* EvJobPageData */ +static void +ev_job_page_data_init (EvJobPageData *job) +{ + EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD; +} + +static gboolean +ev_job_page_data_run (EvJob *job) +{ + EvJobPageData *job_pd = EV_JOB_PAGE_DATA (job); + EvPage *ev_page; + + ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_pd->page, job); + ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job); + + ev_document_doc_mutex_lock (); + ev_page = ev_document_get_page (job->document, job_pd->page); + + if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT) && EV_IS_SELECTION (job->document)) + job_pd->text_mapping = + ev_selection_get_selection_map (EV_SELECTION (job->document), ev_page); + if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document)) + job_pd->link_mapping = + ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_pd->page); + if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document)) + job_pd->form_field_mapping = + ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document), + ev_page); + if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document)) + job_pd->image_mapping = + ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document), + job_pd->page); + if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document)) + job_pd->annot_mapping = + ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document), + ev_page); + g_object_unref (ev_page); + ev_document_doc_mutex_unlock (); + + ev_job_succeeded (job); + + return FALSE; +} + +static void +ev_job_page_data_class_init (EvJobPageDataClass *class) +{ + EvJobClass *job_class = EV_JOB_CLASS (class); + + job_class->run = ev_job_page_data_run; +} + +EvJob * +ev_job_page_data_new (EvDocument *document, + gint page, + EvJobPageDataFlags flags) +{ + EvJobPageData *job; + + ev_debug_message (DEBUG_JOBS, "%d", page); + + job = g_object_new (EV_TYPE_JOB_PAGE_DATA, NULL); + + EV_JOB (job)->document = g_object_ref (document); + job->page = page; + job->flags = flags; + + return EV_JOB (job); +} + /* EvJobThumbnail */ static void ev_job_thumbnail_init (EvJobThumbnail *job) diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h index 4c2fc692..8777d4c4 100644 --- a/libview/ev-jobs.h +++ b/libview/ev-jobs.h @@ -39,6 +39,9 @@ typedef struct _EvJobClass EvJobClass; typedef struct _EvJobRender EvJobRender; typedef struct _EvJobRenderClass EvJobRenderClass; +typedef struct _EvJobPageData EvJobPageData; +typedef struct _EvJobPageDataClass EvJobPageDataClass; + typedef struct _EvJobThumbnail EvJobThumbnail; typedef struct _EvJobThumbnailClass EvJobThumbnailClass; @@ -90,6 +93,11 @@ typedef struct _EvJobPrintClass EvJobPrintClass; #define EV_JOB_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_RENDER, EvJobRenderClass)) #define EV_IS_JOB_RENDER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_RENDER)) +#define EV_TYPE_JOB_PAGE_DATA (ev_job_page_data_get_type()) +#define EV_JOB_PAGE_DATA(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_PAGE_DATA, EvJobPageData)) +#define EV_JOB_PAGE_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_PAGE_DATA, EvJobPageDataClass)) +#define EV_IS_JOB_PAGE_DATA(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_PAGE_DATA)) + #define EV_TYPE_JOB_THUMBNAIL (ev_job_thumbnail_get_type()) #define EV_JOB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_THUMBNAIL, EvJobThumbnail)) #define EV_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_THUMBNAIL, EvJobThumbnailClass)) @@ -189,17 +197,6 @@ struct _EvJobAttachmentsClass EvJobClass parent_class; }; -typedef enum { - EV_RENDER_INCLUDE_NONE = 0, - EV_RENDER_INCLUDE_LINKS = 1 << 0, - EV_RENDER_INCLUDE_TEXT = 1 << 1, - EV_RENDER_INCLUDE_SELECTION = 1 << 2, - EV_RENDER_INCLUDE_IMAGES = 1 << 3, - EV_RENDER_INCLUDE_FORMS = 1 << 4, - EV_RENDER_INCLUDE_ANNOTS = 1 << 5, - EV_RENDER_INCLUDE_ALL = (1 << 6) - 1 -} EvRenderFlags; - struct _EvJobRender { EvJob parent; @@ -214,27 +211,47 @@ struct _EvJobRender gint target_height; cairo_surface_t *surface; - GList *link_mapping; - GdkRegion *text_mapping; - GList *image_mapping; - GList *form_field_mapping; - GList *annots_mapping; - + gboolean include_selection; cairo_surface_t *selection; GdkRegion *selection_region; EvRectangle selection_points; EvSelectionStyle selection_style; GdkColor base; - GdkColor text; - - EvRenderFlags flags; + GdkColor text; }; struct _EvJobRenderClass { EvJobClass parent_class; +}; - void (* page_ready) (EvJobRender *job); +typedef enum { + EV_PAGE_DATA_INCLUDE_NONE = 0, + EV_PAGE_DATA_INCLUDE_LINKS = 1 << 0, + EV_PAGE_DATA_INCLUDE_TEXT = 1 << 1, + EV_PAGE_DATA_INCLUDE_IMAGES = 1 << 2, + EV_PAGE_DATA_INCLUDE_FORMS = 1 << 3, + EV_PAGE_DATA_INCLUDE_ANNOTS = 1 << 4, + EV_PAGE_DATA_INCLUDE_ALL = (1 << 5) - 1 +} EvJobPageDataFlags; + +struct _EvJobPageData +{ + EvJob parent; + + gint page; + EvJobPageDataFlags flags; + + GList *link_mapping; + GList *image_mapping; + GList *form_field_mapping; + GList *annot_mapping; + GdkRegion *text_mapping; +}; + +struct _EvJobPageDataClass +{ + EvJobClass parent_class; }; struct _EvJobThumbnail @@ -387,13 +404,18 @@ EvJob *ev_job_render_new (EvDocument *document, gint rotation, gdouble scale, gint width, - gint height, - EvRenderFlags flags); + gint height); void ev_job_render_set_selection_info (EvJobRender *job, EvRectangle *selection_points, EvSelectionStyle selection_style, GdkColor *text, GdkColor *base); +/* EvJobPageData */ +GType ev_job_page_data_get_type (void) G_GNUC_CONST; +EvJob *ev_job_page_data_new (EvDocument *document, + gint page, + EvJobPageDataFlags flags); + /* EvJobThumbnail */ GType ev_job_thumbnail_get_type (void) G_GNUC_CONST; EvJob *ev_job_thumbnail_new (EvDocument *document, diff --git a/libview/ev-page-cache.c b/libview/ev-page-cache.c new file mode 100644 index 00000000..9835caad --- /dev/null +++ b/libview/ev-page-cache.c @@ -0,0 +1,330 @@ +/* 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. + */ + +#include + +#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" + +typedef struct _EvPageCacheData { + EvJob *job; + gboolean done : 1; + + GList *link_mapping; + GList *image_mapping; + GList *form_field_mapping; + GList *annot_mapping; + GdkRegion *text_mapping; +} EvPageCacheData; + +struct _EvPageCache { + GObject parent; + + EvDocument *document; + EvPageCacheData *page_list; + gint n_pages; + EvJobPageDataFlags flags; +}; + +struct _EvPageCacheClass { + GObjectClass parent_class; +}; + +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_data_free (EvPageCacheData *data) +{ + if (data->job) { + g_object_unref (data->job); + data->job = NULL; + } + + 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 *cache = EV_PAGE_CACHE (object); + gint i; + + if (cache->page_list) { + for (i = 0; i < cache->n_pages; i++) { + EvPageCacheData *data; + + 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); + } + + g_free (cache->page_list); + cache->page_list = NULL; + cache->n_pages = 0; + } + + if (cache->document) { + g_object_unref (cache->document); + cache->document = NULL; + } + + G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object); +} + +static void +ev_page_cache_init (EvPageCache *cache) +{ +} + +static void +ev_page_cache_class_init (EvPageCacheClass *klass) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); + + g_object_class->finalize = ev_page_cache_finalize; +} + +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; +} + +EvPageCache * +ev_page_cache_new (EvDocument *document) +{ + EvPageCache *cache; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + 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 (cache->flags != EV_PAGE_DATA_INCLUDE_NONE) { + cache->page_list = g_new0 (EvPageCacheData, cache->n_pages); + } + + return cache; +} + +static void +job_page_data_finished_cb (EvJob *job, + EvPageCache *cache) +{ + 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_page_range (EvPageCache *cache, + gint start, + gint end) +{ + gint i; + + if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE) + return; + + 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); + } +} + +GList * +ev_page_cache_get_link_mapping (EvPageCache *cache, + gint page) +{ + EvPageCacheData *data; + + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); + + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS)) + return NULL; + + data = &cache->page_list[page]; + if (data->done) + return data->link_mapping; + + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->link_mapping; + + return data->link_mapping; +} + +GList * +ev_page_cache_get_image_mapping (EvPageCache *cache, + gint page) +{ + EvPageCacheData *data; + + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); + + 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; + + return data->image_mapping; +} + +GList * +ev_page_cache_get_form_field_mapping (EvPageCache *cache, + gint page) +{ + EvPageCacheData *data; + + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); + + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS)) + return NULL; + + 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; +} + +GList * +ev_page_cache_get_annot_mapping (EvPageCache *cache, + gint page) +{ + EvPageCacheData *data; + + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); + + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS)) + return NULL; + + data = &cache->page_list[page]; + if (data->done) + return data->annot_mapping; + + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->annot_mapping; + + return data->annot_mapping; +} + +GdkRegion * +ev_page_cache_get_text_mapping (EvPageCache *cache, + gint page) +{ + EvPageCacheData *data; + + g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL); + g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL); + + if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT)) + return NULL; + + data = &cache->page_list[page]; + if (data->done) + return data->text_mapping; + + if (data->job) + return EV_JOB_PAGE_DATA (data->job)->text_mapping; + + return data->text_mapping; +} + diff --git a/libview/ev-page-cache.h b/libview/ev-page-cache.h new file mode 100644 index 00000000..498027d2 --- /dev/null +++ b/libview/ev-page-cache.h @@ -0,0 +1,59 @@ +/* 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. + */ + +#if !defined (__EV_EVINCE_VIEW_H_INSIDE__) && !defined (EVINCE_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef EV_PAGE_CACHE_H +#define EV_PAGE_CACHE_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define EV_TYPE_PAGE_CACHE (ev_page_cache_get_type ()) +#define EV_PAGE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_PAGE_CACHE, EvPageCache)) +#define EV_IS_PAGE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_PAGE_CACHE)) + +typedef struct _EvPageCache EvPageCache; +typedef struct _EvPageCacheClass EvPageCacheClass; + +GType ev_page_cache_get_type (void) G_GNUC_CONST; +EvPageCache *ev_page_cache_new (EvDocument *document); + +void ev_page_cache_set_page_range (EvPageCache *cache, + gint start, + gint end); +GList *ev_page_cache_get_link_mapping (EvPageCache *cache, + gint page); +GList *ev_page_cache_get_image_mapping (EvPageCache *cache, + gint page); +GList *ev_page_cache_get_form_field_mapping (EvPageCache *cache, + gint page); +GList *ev_page_cache_get_annot_mapping (EvPageCache *cache, + gint page); +GdkRegion *ev_page_cache_get_text_mapping (EvPageCache *cache, + gint page); + +G_END_DECLS + +#endif /* EV_PAGE_CACHE_H */ diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c index d0f8644e..8cca5cdd 100644 --- a/libview/ev-pixbuf-cache.c +++ b/libview/ev-pixbuf-cache.c @@ -18,12 +18,7 @@ typedef struct _CacheJobInfo /* Data we get from rendering */ cairo_surface_t *surface; - GList *link_mapping; - GList *image_mapping; - GList *form_field_mapping; - GList *annots_mapping; - GdkRegion *text_mapping; - + /* Selection data. * Selection_points are the coordinates encapsulated in selection. * target_points is the target selection size. */ @@ -77,18 +72,10 @@ static void ev_pixbuf_cache_init (EvPixbufCache *pixbuf_cach static void ev_pixbuf_cache_class_init (EvPixbufCacheClass *pixbuf_cache); static void ev_pixbuf_cache_finalize (GObject *object); static void ev_pixbuf_cache_dispose (GObject *object); -static void job_page_ready_cb (EvJob *job, - EvPixbufCache *pixbuf_cache); static void job_finished_cb (EvJob *job, EvPixbufCache *pixbuf_cache); static CacheJobInfo *find_job_cache (EvPixbufCache *pixbuf_cache, int page); -static void copy_job_to_job_info (EvJobRender *job_render, - CacheJobInfo *job_info, - EvPixbufCache *pixbuf_cache); -static void copy_job_page_and_selection_to_job_info (EvJobRender *job_render, - CacheJobInfo *job_info, - EvPixbufCache *pixbuf_cache); static gboolean new_selection_surface_needed(EvPixbufCache *pixbuf_cache, CacheJobInfo *job_info, gint page, @@ -158,10 +145,8 @@ dispose_cache_job_info (CacheJobInfo *job_info, { if (job_info == NULL) return; + if (job_info->job) { - g_signal_handlers_disconnect_by_func (job_info->job, - G_CALLBACK (job_page_ready_cb), - data); g_signal_handlers_disconnect_by_func (job_info->job, G_CALLBACK (job_finished_cb), data); @@ -177,26 +162,6 @@ dispose_cache_job_info (CacheJobInfo *job_info, gdk_region_destroy (job_info->region); job_info->region = NULL; } - if (job_info->link_mapping) { - ev_mapping_list_free (job_info->link_mapping, g_object_unref); - job_info->link_mapping = NULL; - } - if (job_info->image_mapping) { - ev_mapping_list_free (job_info->image_mapping, g_object_unref); - job_info->image_mapping = NULL; - } - if (job_info->form_field_mapping) { - ev_mapping_list_free (job_info->form_field_mapping, g_object_unref); - job_info->form_field_mapping = NULL; - } - if (job_info->annots_mapping) { - ev_mapping_list_free (job_info->annots_mapping, g_object_unref); - job_info->annots_mapping = NULL; - } - if (job_info->text_mapping) { - gdk_region_destroy (job_info->text_mapping); - job_info->text_mapping = NULL; - } if (job_info->selection) { cairo_surface_destroy (job_info->selection); job_info->selection = NULL; @@ -249,23 +214,56 @@ ev_pixbuf_cache_new (GtkWidget *view, } static void -job_page_ready_cb (EvJob *job, - EvPixbufCache *pixbuf_cache) +copy_job_to_job_info (EvJobRender *job_render, + CacheJobInfo *job_info, + EvPixbufCache *pixbuf_cache) { - CacheJobInfo *job_info; - EvJobRender *job_render = EV_JOB_RENDER (job); + if (job_info->rc == NULL) { + job_info->rc = ev_render_context_new (job_render->ev_page, + job_render->rotation, + job_render->scale); + } else { + ev_render_context_set_page (job_info->rc, job_render->ev_page); + ev_render_context_set_rotation (job_info->rc, job_render->rotation); + ev_render_context_set_scale (job_info->rc, job_render->scale); + } - /* If the job is outside of our interest, we silently discard it */ - if ((job_render->page < (pixbuf_cache->start_page - pixbuf_cache->preload_cache_size)) || - (job_render->page > (pixbuf_cache->end_page + pixbuf_cache->preload_cache_size))) { - g_object_unref (job); - return; + if (job_info->surface) { + cairo_surface_destroy (job_info->surface); + } + job_info->surface = cairo_surface_reference (job_render->surface); + if (pixbuf_cache->inverted_colors) { + ev_document_misc_invert_surface (job_info->surface); } - job_info = find_job_cache (pixbuf_cache, job_render->page); + job_info->points_set = FALSE; + if (job_render->include_selection) { + if (job_info->selection) { + cairo_surface_destroy (job_info->selection); + job_info->selection = NULL; + } + if (job_info->selection_region) { + gdk_region_destroy (job_info->selection_region); + job_info->selection_region = NULL; + } - copy_job_page_and_selection_to_job_info (job_render, job_info, pixbuf_cache); - g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region); + job_info->selection_points = job_render->selection_points; + job_info->selection_region = gdk_region_copy (job_render->selection_region); + job_info->selection = cairo_surface_reference (job_render->selection); + g_assert (job_info->selection_points.x1 >= 0); + job_info->points_set = TRUE; + } + + if (job_info->job) { + g_signal_handlers_disconnect_by_func (job_info->job, + G_CALLBACK (job_finished_cb), + pixbuf_cache); + ev_job_cancel (job_info->job); + g_object_unref (job_info->job); + job_info->job = NULL; + } + + job_info->page_ready = TRUE; } static void @@ -283,7 +281,9 @@ job_finished_cb (EvJob *job, } job_info = find_job_cache (pixbuf_cache, job_render->page); + copy_job_to_job_info (job_render, job_info, pixbuf_cache); + g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region); } /* This checks a job to see if the job would generate the right sized pixbuf @@ -310,9 +310,6 @@ check_job_size_and_unref (EvPixbufCache *pixbuf_cache, height == EV_JOB_RENDER (job_info->job)->target_height) return; - g_signal_handlers_disconnect_by_func (job_info->job, - G_CALLBACK (job_page_ready_cb), - pixbuf_cache); g_signal_handlers_disconnect_by_func (job_info->job, G_CALLBACK (job_finished_cb), pixbuf_cache); @@ -372,10 +369,6 @@ move_one_job (CacheJobInfo *job_info, job_info->job = NULL; job_info->region = NULL; job_info->surface = NULL; - job_info->link_mapping = NULL; - job_info->image_mapping = NULL; - job_info->form_field_mapping = NULL; - job_info->annots_mapping = NULL; if (new_priority != priority && target_page->job) { ev_job_scheduler_update_job (target_page->job, new_priority); @@ -450,108 +443,6 @@ ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache, pixbuf_cache->end_page = end_page; } -static void -copy_job_page_and_selection_to_job_info (EvJobRender *job_render, - CacheJobInfo *job_info, - EvPixbufCache *pixbuf_cache) -{ - if (job_info->rc == NULL) { - job_info->rc = ev_render_context_new (job_render->ev_page, - job_render->rotation, - job_render->scale); - } else { - ev_render_context_set_page (job_info->rc, job_render->ev_page); - ev_render_context_set_rotation (job_info->rc, job_render->rotation); - ev_render_context_set_scale (job_info->rc, job_render->scale); - } - - if (job_info->surface) { - cairo_surface_destroy (job_info->surface); - } - job_info->surface = cairo_surface_reference (job_render->surface); - if (pixbuf_cache->inverted_colors) { - ev_document_misc_invert_surface (job_info->surface); - } - - job_info->points_set = FALSE; - if (job_render->flags & EV_RENDER_INCLUDE_SELECTION) { - if (job_info->selection) { - cairo_surface_destroy (job_info->selection); - job_info->selection = NULL; - } - if (job_info->selection_region) { - gdk_region_destroy (job_info->selection_region); - job_info->selection_region = NULL; - } - - job_info->selection_points = job_render->selection_points; - job_info->selection_region = gdk_region_copy (job_render->selection_region); - job_info->selection = cairo_surface_reference (job_render->selection); - g_assert (job_info->selection_points.x1 >= 0); - job_info->points_set = TRUE; - } - - if (job_info->job) { - g_signal_handlers_disconnect_by_func (job_info->job, - G_CALLBACK (job_page_ready_cb), - pixbuf_cache); - } - - job_info->page_ready = TRUE; -} - -static void -copy_job_to_job_info (EvJobRender *job_render, - CacheJobInfo *job_info, - EvPixbufCache *pixbuf_cache) -{ - if (!job_info->page_ready) { - g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region); - copy_job_page_and_selection_to_job_info (job_render, - job_info, - pixbuf_cache); - } - - if (job_render->flags & EV_RENDER_INCLUDE_LINKS) { - if (job_info->link_mapping) - ev_mapping_list_free (job_info->link_mapping, g_object_unref); - job_info->link_mapping = job_render->link_mapping; - } - - if (job_render->flags & EV_RENDER_INCLUDE_IMAGES) { - if (job_info->image_mapping) - ev_mapping_list_free (job_info->image_mapping, g_object_unref); - job_info->image_mapping = job_render->image_mapping; - } - - if (job_render->flags & EV_RENDER_INCLUDE_FORMS) { - if (job_info->form_field_mapping) - ev_mapping_list_free (job_info->form_field_mapping, g_object_unref); - job_info->form_field_mapping = job_render->form_field_mapping; - } - - if (job_render->flags & EV_RENDER_INCLUDE_ANNOTS) { - if (job_info->annots_mapping) - ev_mapping_list_free (job_info->annots_mapping, g_object_unref); - job_info->annots_mapping = job_render->annots_mapping; - } - - if (job_render->flags & EV_RENDER_INCLUDE_TEXT) { - if (job_info->text_mapping) - gdk_region_destroy (job_info->text_mapping); - job_info->text_mapping = job_render->text_mapping; - } - - if (job_info->job) { - g_signal_handlers_disconnect_by_func (job_info->job, - G_CALLBACK (job_finished_cb), - pixbuf_cache); - ev_job_cancel (job_info->job); - g_object_unref (job_info->job); - job_info->job = NULL; - } -} - static CacheJobInfo * find_job_cache (EvPixbufCache *pixbuf_cache, int page) @@ -623,31 +514,16 @@ add_job (EvPixbufCache *pixbuf_cache, gfloat scale, EvJobPriority priority) { - EvRenderFlags flags = 0; - job_info->page_ready = FALSE; - + if (job_info->region) gdk_region_destroy (job_info->region); job_info->region = region ? gdk_region_copy (region) : NULL; - /* Figure out what else we need for this job */ - if (job_info->link_mapping == NULL) - flags |= EV_RENDER_INCLUDE_LINKS; - if (job_info->image_mapping == NULL) - flags |= EV_RENDER_INCLUDE_IMAGES; - if (job_info->form_field_mapping == NULL) - flags |= EV_RENDER_INCLUDE_FORMS; - if (job_info->annots_mapping == NULL) - flags |= EV_RENDER_INCLUDE_ANNOTS; - if (job_info->text_mapping == NULL) - flags |= EV_RENDER_INCLUDE_TEXT; - job_info->job = ev_job_render_new (pixbuf_cache->document, page, rotation, scale, - width, height, - flags); - + width, height); + if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) { GdkColor *text, *base; @@ -659,9 +535,6 @@ add_job (EvPixbufCache *pixbuf_cache, text, base); } - g_signal_connect (job_info->job, "page-ready", - G_CALLBACK (job_page_ready_cb), - pixbuf_cache); g_signal_connect (job_info->job, "finished", G_CALLBACK (job_finished_cb), pixbuf_cache); @@ -807,102 +680,17 @@ ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache, if (job_info->page_ready) return job_info->surface; - + /* We don't need to wait for the idle to handle the callback */ if (job_info->job && EV_JOB_RENDER (job_info->job)->page_ready) { - copy_job_page_and_selection_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); + copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region); } return job_info->surface; } -GList * -ev_pixbuf_cache_get_link_mapping (EvPixbufCache *pixbuf_cache, - gint page) -{ - CacheJobInfo *job_info; - - job_info = find_job_cache (pixbuf_cache, page); - if (job_info == NULL) - return NULL; - - /* We don't need to wait for the idle to handle the callback */ - if (job_info->job && - EV_JOB (job_info->job)->finished) { - copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); - } - - return job_info->link_mapping; -} - -GList * -ev_pixbuf_cache_get_image_mapping (EvPixbufCache *pixbuf_cache, - gint page) -{ - CacheJobInfo *job_info; - - if (!EV_IS_DOCUMENT_IMAGES (pixbuf_cache->document)) - return NULL; - - job_info = find_job_cache (pixbuf_cache, page); - if (job_info == NULL) - return NULL; - - /* We don't need to wait for the idle to handle the callback */ - if (job_info->job && - EV_JOB (job_info->job)->finished) { - copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); - } - - return job_info->image_mapping; -} - -GList * -ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache, - gint page) -{ - CacheJobInfo *job_info; - - if (!EV_IS_DOCUMENT_FORMS (pixbuf_cache->document)) - return NULL; - - job_info = find_job_cache (pixbuf_cache, page); - if (job_info == NULL) - return NULL; - - /* We don't need to wait for the idle to handle the callback */ - if (job_info->job && - EV_JOB (job_info->job)->finished) { - copy_job_to_job_info (EV_JOB_RENDER(job_info->job), job_info, pixbuf_cache); - } - - return job_info->form_field_mapping; -} - -GList * -ev_pixbuf_cache_get_annots_mapping (EvPixbufCache *pixbuf_cache, - gint page) -{ - CacheJobInfo *job_info; - - if (!EV_IS_DOCUMENT_ANNOTATIONS (pixbuf_cache->document)) - return NULL; - - job_info = find_job_cache (pixbuf_cache, page); - if (job_info == NULL) - return NULL; - - /* We don't need to wait for the idle to handle the callback */ - if (job_info->job && - EV_JOB (job_info->job)->finished) { - copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); - } - - return job_info->annots_mapping; -} - static gboolean new_selection_surface_needed (EvPixbufCache *pixbuf_cache, CacheJobInfo *job_info, @@ -944,25 +732,6 @@ clear_selection_if_needed (EvPixbufCache *pixbuf_cache, } } -GdkRegion * -ev_pixbuf_cache_get_text_mapping (EvPixbufCache *pixbuf_cache, - gint page) -{ - CacheJobInfo *job_info; - - job_info = find_job_cache (pixbuf_cache, page); - if (job_info == NULL) - return NULL; - - /* We don't need to wait for the idle to handle the callback */ - if (job_info->job && - EV_JOB (job_info->job)->finished) { - copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); - } - - return job_info->text_mapping; -} - /* Clears the cache of jobs and pixbufs. */ void @@ -1048,7 +817,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, /* If we have a running job, we just return what we have under the * assumption that it'll be updated later and we can scale it as need * be */ - if (job_info->job && (EV_JOB_RENDER (job_info->job)->flags & EV_RENDER_INCLUDE_SELECTION)) + if (job_info->job && EV_JOB_RENDER (job_info->job)->include_selection) return job_info->selection; /* Now, lets see if we need to resize the image. If we do, we clear the diff --git a/libview/ev-pixbuf-cache.h b/libview/ev-pixbuf-cache.h index 94673c2e..514e09dc 100644 --- a/libview/ev-pixbuf-cache.h +++ b/libview/ev-pixbuf-cache.h @@ -64,16 +64,6 @@ void ev_pixbuf_cache_set_page_range (EvPixbufCache *pixbuf_cache GList *selection_list); cairo_surface_t *ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache, gint page); -GList *ev_pixbuf_cache_get_link_mapping (EvPixbufCache *pixbuf_cache, - gint page); -GList *ev_pixbuf_cache_get_image_mapping (EvPixbufCache *pixbuf_cache, - gint page); -GdkRegion *ev_pixbuf_cache_get_text_mapping (EvPixbufCache *pixbuf_cache, - gint page); -GList *ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache, - gint page); -GList *ev_pixbuf_cache_get_annots_mapping (EvPixbufCache *pixbuf_cache, - gint page); void ev_pixbuf_cache_clear (EvPixbufCache *pixbuf_cache); void ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache); void ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache, diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 76998d37..7bd16e91 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -28,6 +28,7 @@ #include "ev-view.h" #include "ev-document-model.h" #include "ev-pixbuf-cache.h" +#include "ev-page-cache.h" #include "ev-jobs.h" #include "ev-image.h" #include "ev-form-field.h" @@ -136,6 +137,7 @@ struct _EvView { EvDocumentModel *model; EvPixbufCache *pixbuf_cache; + EvPageCache *page_cache; EvHeightToPageCache *height_to_page_cache; EvViewCursor cursor; EvJobRender *current_job; diff --git a/libview/ev-view.c b/libview/ev-view.c index 44f06cd7..dc314ec9 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -35,6 +35,7 @@ #include "ev-document-misc.h" #include "ev-document-transition.h" #include "ev-pixbuf-cache.h" +#include "ev-page-cache.h" #include "ev-transition-animation.h" #include "ev-view-marshal.h" #include "ev-document-annotations.h" @@ -734,6 +735,9 @@ view_update_range_and_current_page (EvView *view) } } + ev_page_cache_set_page_range (view->page_cache, + view->start_page, + view->end_page); ev_pixbuf_cache_set_page_range (view->pixbuf_cache, view->start_page, view->end_page, @@ -829,7 +833,7 @@ compute_scroll_increment (EvView *view, page = scroll == GTK_SCROLL_PAGE_BACKWARD ? view->start_page : view->end_page; - text_region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page); + text_region = ev_page_cache_get_text_mapping (view->page_cache, page); if (!text_region || gdk_region_empty (text_region)) return adjustment->page_size; @@ -1379,7 +1383,7 @@ location_in_text (EvView *view, if (page == -1) return FALSE; - region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page); + region = ev_page_cache_get_text_mapping (view->page_cache, page); if (region) return gdk_region_point_in (region, x_offset / view->scale, y_offset / view->scale); @@ -1514,7 +1518,7 @@ ev_view_get_link_at_location (EvView *view, if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new)) return NULL; - link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page); + link_mapping = ev_page_cache_get_link_mapping (view->page_cache, page); if (link_mapping) return ev_mapping_list_get_data (link_mapping, x_new, y_new); @@ -1932,7 +1936,7 @@ ev_view_get_image_at_location (EvView *view, if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new)) return NULL; - image_mapping = ev_pixbuf_cache_get_image_mapping (view->pixbuf_cache, page); + image_mapping = ev_page_cache_get_image_mapping (view->page_cache, page); if (image_mapping) return ev_mapping_list_get_data (image_mapping, x_new, y_new); @@ -1956,7 +1960,7 @@ ev_view_get_form_field_at_location (EvView *view, if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new)) return NULL; - forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, page); + forms_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, page); if (forms_mapping) return ev_mapping_list_get_data (forms_mapping, x_new, y_new); @@ -1971,8 +1975,8 @@ ev_view_form_field_get_region (EvView *view, GdkRectangle view_area; GList *forms_mapping; - forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page->index); + forms_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, + field->page->index); ev_view_get_area_from_mapping (view, field->page->index, forms_mapping, field, &view_area); @@ -2023,8 +2027,8 @@ ev_view_form_field_button_create_widget (EvView *view, /* For radio buttons and checkbox buttons that are in a set * we need to update also the region for the current selected item */ - forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page->index); + forms_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, + field->page->index); for (l = forms_mapping; l; l = g_list_next (l)) { EvFormField *button = ((EvMapping *)(l->data))->data; GdkRegion *button_region; @@ -2407,7 +2411,8 @@ ev_view_handle_form_field (EvView *view, g_object_ref (field), (GDestroyNotify)g_object_unref); - form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, field->page->index); + form_field_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, + field->page->index); ev_view_get_area_from_mapping (view, field->page->index, form_field_mapping, field, &view_area); @@ -2631,7 +2636,7 @@ show_annotation_windows (EvView *view, parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); - annots = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page); + annots = ev_page_cache_get_annot_mapping (view->page_cache, page); for (l = annots; l && l->data; l = g_list_next (l)) { EvAnnotation *annot; @@ -2696,7 +2701,7 @@ hide_annotation_windows (EvView *view, { GList *annots, *l; - annots = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page); + annots = ev_page_cache_get_annot_mapping (view->page_cache, page); for (l = annots; l && l->data; l = g_list_next (l)) { EvAnnotation *annot; @@ -2728,7 +2733,7 @@ ev_view_get_annotation_at_location (EvView *view, if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new)) return NULL; - annotations_mapping = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page); + annotations_mapping = ev_page_cache_get_annot_mapping (view->page_cache, page); if (annotations_mapping) return ev_mapping_list_get_data (annotations_mapping, x_new, y_new); @@ -2965,8 +2970,8 @@ ev_view_size_allocate (GtkWidget *widget, if (!field) continue; - form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, - field->page->index); + form_field_mapping = ev_page_cache_get_form_field_mapping (view->page_cache, + field->page->index); ev_view_get_area_from_mapping (view, field->page->index, form_field_mapping, field, &view_area); @@ -3220,7 +3225,7 @@ ev_view_expose_event (GtkWidget *widget, return FALSE; cr = gdk_cairo_create (view->layout.bin_window); - + for (i = view->start_page; i >= 0 && i <= view->end_page; i++) { GdkRectangle page_area; GtkBorder border; @@ -3305,7 +3310,7 @@ get_link_area (EvView *view, find_page_at_location (view, x, y, &page, &x_offset, &y_offset); - link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page); + link_mapping = ev_page_cache_get_link_mapping (view->page_cache, page); ev_view_get_area_from_mapping (view, page, link_mapping, link, area); @@ -3318,7 +3323,7 @@ get_annot_area (EvView *view, EvAnnotation *annot, GdkRectangle *area) { - GList *annots_mapping; + GList *annot_mapping; gint page; gint x_offset = 0, y_offset = 0; @@ -3327,9 +3332,9 @@ get_annot_area (EvView *view, find_page_at_location (view, x, y, &page, &x_offset, &y_offset); - annots_mapping = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page); + annot_mapping = ev_page_cache_get_annot_mapping (view->page_cache, page); ev_view_get_area_from_mapping (view, page, - annots_mapping, + annot_mapping, annot, area); } @@ -4565,6 +4570,11 @@ ev_view_destroy (GtkObject *object) view->pixbuf_cache = NULL; } + if (view->page_cache) { + g_object_unref (view->page_cache); + view->page_cache = NULL; + } + if (view->goto_window) { gtk_widget_destroy (view->goto_window); view->goto_window = NULL; @@ -5107,6 +5117,7 @@ setup_caches (EvView *view) view->height_to_page_cache = ev_view_get_height_to_page_cache (view); view->pixbuf_cache = ev_pixbuf_cache_new (GTK_WIDGET (view), view->document); + view->page_cache = ev_page_cache_new (view->document); inverted_colors = ev_document_model_get_inverted_colors (view->model); ev_pixbuf_cache_set_inverted_colors (view->pixbuf_cache, inverted_colors); g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view); @@ -5119,6 +5130,11 @@ clear_caches (EvView *view) g_object_unref (view->pixbuf_cache); view->pixbuf_cache = NULL; } + + if (view->page_cache) { + g_object_unref (view->page_cache); + view->page_cache = NULL; + } } void -- 2.43.5