+/* 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-page-cache.h"
-#include "ev-document-thumbnails.h"
-#include "ev-page.h"
-#include <stdlib.h>
-#include <string.h>
-struct _EvPageCache
-{
- GObject parent;
+#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"
- EvDocument *document;
+typedef struct _EvPageCacheData {
+ EvJob *job;
+ gboolean done : 1;
- gint current_page;
+ GList *link_mapping;
+ GList *image_mapping;
+ GList *form_field_mapping;
+ GList *annot_mapping;
+ GdkRegion *text_mapping;
+} EvPageCacheData;
- gboolean dual_even_left;
+struct _EvPageCache {
+ GObject parent;
- int rotation;
+ EvDocument *document;
+ EvPageCacheData *page_list;
+ gint n_pages;
+ EvJobPageDataFlags flags;
};
-struct _EvPageCacheClass
-{
+struct _EvPageCacheClass {
GObjectClass parent_class;
-
- void (* page_changed) (EvPageCache *page_cache, gint page);
- void (* history_changed) (EvPageCache *page_cache, gint page);
};
-enum
+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)
{
- PAGE_CHANGED,
- HISTORY_CHANGED,
- N_SIGNALS,
-};
+ if (data->job) {
+ g_object_unref (data->job);
+ data->job = NULL;
+ }
-static guint signals[N_SIGNALS] = {0, };
+ if (data->link_mapping) {
+ ev_mapping_list_free (data->link_mapping, g_object_unref);
+ data->link_mapping = NULL;
+ }
-static void ev_page_cache_init (EvPageCache *page_cache);
-static void ev_page_cache_class_init (EvPageCacheClass *page_cache);
-static void ev_page_cache_finalize (GObject *object);
+ if (data->image_mapping) {
+ ev_mapping_list_free (data->image_mapping, g_object_unref);
+ data->image_mapping = NULL;
+ }
-G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
+ 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_init (EvPageCache *page_cache)
+ev_page_cache_finalize (GObject *object)
{
- page_cache->current_page = -1;
+ 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_class_init (EvPageCacheClass *class)
+ev_page_cache_init (EvPageCache *cache)
{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = ev_page_cache_finalize;
-
- signals [PAGE_CHANGED] =
- g_signal_new ("page-changed",
- EV_TYPE_PAGE_CACHE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EvPageCacheClass, page_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1,
- G_TYPE_INT);
-
- signals [HISTORY_CHANGED] =
- g_signal_new ("history-changed",
- EV_TYPE_PAGE_CACHE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EvPageCacheClass, history_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1,
- G_TYPE_INT);
-
}
static void
-ev_page_cache_finalize (GObject *object)
+ev_page_cache_class_init (EvPageCacheClass *klass)
{
- EvPageCache *page_cache = EV_PAGE_CACHE (object);
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
- page_cache->document = NULL;
+ g_object_class->finalize = ev_page_cache_finalize;
+}
- G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
+static EvJobPageDataFlags
+get_flags_for_document (EvDocument *document)
+{
+ EvJobPageDataFlags flags = EV_PAGE_DATA_INCLUDE_NONE;
+
+ if (EV_IS_DOCUMENT_LINKS (document))
+ flags |= EV_PAGE_DATA_INCLUDE_LINKS;
+ if (EV_IS_DOCUMENT_IMAGES (document))
+ flags |= EV_PAGE_DATA_INCLUDE_IMAGES;
+ if (EV_IS_DOCUMENT_FORMS (document))
+ flags |= EV_PAGE_DATA_INCLUDE_FORMS;
+ if (EV_IS_DOCUMENT_ANNOTATIONS (document))
+ flags |= EV_PAGE_DATA_INCLUDE_ANNOTS;
+ if (EV_IS_SELECTION (document))
+ flags |= EV_PAGE_DATA_INCLUDE_TEXT;
+
+ return flags;
}
-static EvPageCache *
+EvPageCache *
ev_page_cache_new (EvDocument *document)
{
- EvPageCache *page_cache;
+ EvPageCache *cache;
- page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL);
- page_cache->document = document;
+ g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
- if (ev_document_get_n_pages (page_cache->document) > 0)
- ev_page_cache_set_current_page (page_cache, 0);
+ 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);
- return page_cache;
+ if (cache->flags != EV_PAGE_DATA_INCLUDE_NONE) {
+ cache->page_list = g_new0 (EvPageCacheData, cache->n_pages);
+ }
+
+ return cache;
}
-gint
-ev_page_cache_get_current_page (EvPageCache *page_cache)
+static void
+job_page_data_finished_cb (EvJob *job,
+ EvPageCache *cache)
{
- g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
-
- return page_cache->current_page;
+ EvJobPageData *job_data = EV_JOB_PAGE_DATA (job);
+ EvPageCacheData *data;
+
+ data = &cache->page_list[job_data->page];
+ data->link_mapping = job_data->link_mapping;
+ data->image_mapping = job_data->image_mapping;
+ data->form_field_mapping = job_data->form_field_mapping;
+ data->annot_mapping = job_data->annot_mapping;
+ data->text_mapping = job_data->text_mapping;
+ data->done = TRUE;
+
+ g_object_unref (data->job);
+ data->job = NULL;
}
void
-ev_page_cache_set_current_page (EvPageCache *page_cache,
- int page)
+ev_page_cache_set_page_range (EvPageCache *cache,
+ gint start,
+ gint end)
{
- g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
+ gint i;
- if (page == page_cache->current_page)
+ if (cache->flags == EV_PAGE_DATA_INCLUDE_NONE)
return;
- page_cache->current_page = page;
- g_signal_emit (page_cache, signals[PAGE_CHANGED], 0, page);
+ for (i = start; i <= end; i++) {
+ EvPageCacheData *data = &cache->page_list[i];
+
+ if (data->done || data->job)
+ continue;
+
+ data->job = ev_job_page_data_new (cache->document, i, cache->flags);
+ g_signal_connect (data->job, "finished",
+ G_CALLBACK (job_page_data_finished_cb),
+ cache);
+ ev_job_scheduler_push_job (data->job, EV_JOB_PRIORITY_NONE);
+ }
+}
+
+EvJobPageDataFlags
+ev_page_cache_get_flags (EvPageCache *cache)
+{
+ return cache->flags;
}
void
-ev_page_cache_set_current_page_history (EvPageCache *page_cache,
- int page)
+ev_page_cache_set_flags (EvPageCache *cache,
+ EvJobPageDataFlags flags)
{
- if (abs (page - page_cache->current_page) > 1)
- g_signal_emit (page_cache, signals [HISTORY_CHANGED], 0, page);
-
- ev_page_cache_set_current_page (page_cache, page);
+ cache->flags = flags;
}
-gboolean
-ev_page_cache_set_page_label (EvPageCache *page_cache,
- const gchar *page_label)
+GList *
+ev_page_cache_get_link_mapping (EvPageCache *cache,
+ gint page)
{
- gint page;
+ EvPageCacheData *data;
- g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
+ g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
+ g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
- if (ev_document_find_page_by_label (page_cache->document, page_label, &page)) {
- ev_page_cache_set_current_page (page_cache, page);
- return TRUE;
- }
+ if (!(cache->flags & EV_PAGE_DATA_INCLUDE_LINKS))
+ return NULL;
+
+ data = &cache->page_list[page];
+ if (data->done)
+ return data->link_mapping;
- return FALSE;
+ if (data->job)
+ return EV_JOB_PAGE_DATA (data->job)->link_mapping;
+
+ return data->link_mapping;
}
-void
-ev_page_cache_get_size (EvPageCache *page_cache,
- gint page,
- gint rotation,
- gfloat scale,
- gint *width,
- gint *height)
+GList *
+ev_page_cache_get_image_mapping (EvPageCache *cache,
+ gint page)
{
- double w, h;
+ EvPageCacheData *data;
- g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
+ g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
+ g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
- ev_document_get_page_size (page_cache->document, page, &w, &h);
+ if (!(cache->flags & EV_PAGE_DATA_INCLUDE_IMAGES))
+ return NULL;
- w = w * scale + 0.5;
- h = h * scale + 0.5;
+ data = &cache->page_list[page];
+ if (data->done)
+ return data->image_mapping;
- if (rotation == 0 || rotation == 180) {
- if (width) *width = (int)w;
- if (height) *height = (int)h;
- } else {
- if (width) *width = (int)h;
- if (height) *height = (int)w;
- }
+ if (data->job)
+ return EV_JOB_PAGE_DATA (data->job)->image_mapping;
+
+ return data->image_mapping;
}
-void
-ev_page_cache_get_max_width (EvPageCache *page_cache,
- gint rotation,
- gfloat scale,
- gint *width)
+GList *
+ev_page_cache_get_form_field_mapping (EvPageCache *cache,
+ gint page)
{
- double w, h;
+ EvPageCacheData *data;
- g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
+ g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
+ g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
- if (!width)
- return;
+ if (!(cache->flags & EV_PAGE_DATA_INCLUDE_FORMS))
+ return NULL;
+
+ data = &cache->page_list[page];
+ if (data->done)
+ return data->form_field_mapping;
- ev_document_get_max_page_size (page_cache->document, &w, &h);
- *width = (rotation == 0 || rotation == 180) ? w * scale : h * scale;
+ if (data->job)
+ return EV_JOB_PAGE_DATA (data->job)->form_field_mapping;
+
+ return data->form_field_mapping;
}
-void
-ev_page_cache_get_max_height (EvPageCache *page_cache,
- gint rotation,
- gfloat scale,
- gint *height)
+GList *
+ev_page_cache_get_annot_mapping (EvPageCache *cache,
+ gint page)
{
- double w, h;
+ EvPageCacheData *data;
- g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
+ g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
+ g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
- if (!height)
- return;
+ if (!(cache->flags & EV_PAGE_DATA_INCLUDE_ANNOTS))
+ return NULL;
- ev_document_get_max_page_size (page_cache->document, &w, &h);
- *height = (rotation == 0 || rotation == 180) ? h * scale : w * scale;
-}
+ data = &cache->page_list[page];
+ if (data->done)
+ return data->annot_mapping;
-#define PAGE_CACHE_STRING "ev-page-cache"
+ if (data->job)
+ return EV_JOB_PAGE_DATA (data->job)->annot_mapping;
-EvPageCache *
-ev_page_cache_get (EvDocument *document)
+ return data->annot_mapping;
+}
+
+GdkRegion *
+ev_page_cache_get_text_mapping (EvPageCache *cache,
+ gint page)
{
- EvPageCache *page_cache;
+ EvPageCacheData *data;
- g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
+ g_return_val_if_fail (EV_IS_PAGE_CACHE (cache), NULL);
+ g_return_val_if_fail (page >= 0 && page < cache->n_pages, NULL);
- page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING);
- if (page_cache == NULL) {
- page_cache = ev_page_cache_new (document);
- g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref);
- }
+ if (!(cache->flags & EV_PAGE_DATA_INCLUDE_TEXT))
+ return NULL;
+
+ data = &cache->page_list[page];
+ if (data->done)
+ return data->text_mapping;
- return page_cache;
+ if (data->job)
+ return EV_JOB_PAGE_DATA (data->job)->text_mapping;
+
+ return data->text_mapping;
}
+