[evince] [libview] Split EvPixbufCache into dynamic and static data



commit 3a8589a7c5e0394df456074048845cddd04bc43d
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Tue Dec 8 18:23:50 2009 +0100

    [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(-)
---
diff --git a/help/reference/libview/libevview.types b/help/reference/libview/libevview.types
index c98d870..003f08c 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 ef38f99..03b8d6d 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 620ea66..d13c06b 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);
@@ -73,11 +75,6 @@ enum {
 };
 
 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)
@@ -476,33 +473,6 @@ ev_job_render_dispose (GObject *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)
 {
 	EvJobRender     *job_render = EV_JOB_RENDER (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 4c2fc69..8777d4c 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 0000000..9835caa
--- /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 <config.h>
+
+#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 0000000..498027d
--- /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 <evince-view.h> can be included directly."
+#endif
+
+#ifndef EV_PAGE_CACHE_H
+#define EV_PAGE_CACHE_H
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+#include <evince-document.h>
+
+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 d0f8644..8cca5cd 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,11 +145,9 @@ 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);
 		ev_job_cancel (job_info->job);
@@ -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
@@ -311,9 +311,6 @@ check_job_size_and_unref (EvPixbufCache *pixbuf_cache,
 		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);
 	ev_job_cancel (job_info->job);
@@ -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 94673c2..514e09d 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 76998d3..7bd16e9 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 44f06cd..dc314ec 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]