Big patch, and a partial return to normalcy



Hi,

I am attaching a big patch that I'm going to commit soon.  It requires
the latest poppler from CVS.  Since the patch is big, I thought I'd list
the changes it introduces.

 * Re-adds links to the document.  You can click on them again.

 * Speeds up (with a fix in poppler) the creation of the index from 10
   seconds to less than .1 seconds.  We also don't slowly fill things in
   like before, meaning expand-all will actually expand all.

 * Moves the pdf backend to use to poppler-glib.  Kristian and I have
   been cleaning up this API over the last week.  It's much nicer, and
   is going to let us reenable the searching.

 * Changes ev-document page indexing to be '0' based again.  We were '1'
   based for a while, but we're back to '0'.  The reason for this change
   is that we now can get page labels from both .ps and .pdf, which
   means the need to keep the index the same as the human-readable index
   has gone.  Unfortunately, bits of xpdf still index by 1, but they're
   slowly being excised.

 * Fixes some bugs in the pixbuf-cache.

 * This also introduces a minor regression from the last commit --
   printing doesn't work yet.  I will get that going shortly.  It just
   involves moving some code around.

 * Disables the pixbuf backend.  I'm going to disable it until we can
   find a new maintainer.

Status:
=======

Once that's committed, we have two major features from the pre-threaded
days left to be implemented.  They are selection and searching.

Kristian and I are reasonably confident that we can get both of these
working like before.  However, we don't really like the way that
selection currently works and search gets updated.  I think I'm okay
with turning off selection for now, and focusing mostly on search.  Once
that's done, we should make a release.

I think that this is basically the last of the really big changes (for
now).  When searching lands, we can start working on doing interesting
features again instead of rewriting the core.  I'm pretty excited about
being able to implement continuous scrolling, and there are a lot of
neat things we can do.  One cool thing we can think about doing is
adding A11Y support for the documents themselves.  Another neat feature
would be Brian's scrolling suggestions (see #170871).  Also, we now can
get access to a page label (such as "iii" instead of "3").  We should
use that.

Thanks,
-Jonathan

? evince-glib.patch
? pdf/attachment.cgi?id=39233
? pixbuf/pixbuf-document.loT
? shell/Japan Tour3.tif
? shell/U206G_InFlight2.svg
? shell/cvs.ps
? shell/forjrb.passwd
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evince/ChangeLog,v
retrieving revision 1.255
diff -u -p -r1.255 ChangeLog
--- ChangeLog	25 Mar 2005 21:57:13 -0000	1.255
+++ ChangeLog	31 Mar 2005 07:33:35 -0000
@@ -1,3 +1,58 @@
+Thu Mar 31 01:21:58 2005  Jonathan Blandford  <jrb redhat com>
+
+	* Makefile.am: Remove pixbuf backend for now
+
+	* configure.ac: Require poppler-glib instead of just poppler.
+
+	* backend/ev-document-thumbnails.h: Add a comment
+
+	* backend/ev-document.h:
+	* backend/ev-document.c: (ev_document_class_init),
+	(ev_document_load), (ev_document_get_link),
+	(ev_document_get_links): Remove 3 methods and add get_links.
+	Also, made 0 based.
+
+	* backend/ev-jobs.c: (ev_job_render_new), (ev_job_render_run):
+	* backend/ev-jobs.h: now EvJobRender can grab the links for a document.
+
+	* backend/ev-link.c: (ev_link_set_title),
+	(ev_link_mapping_free_foreach), (ev_link_mapping_free),
+	(ev_link_mapping_find):
+	* backend/ev-link.h: Allow NULL titles.  Also, introduce a mapping link.
+	
+	* backend/ev-page-cache.c: (ev_page_cache_init),
+	(_ev_page_cache_new), (ev_page_cache_set_current_page),
+	(ev_page_cache_get_size), (ev_page_cache_next_page),
+	(ev_page_cache_prev_page): Fix to be 0 based.
+
+	* pdf/Makefile.am: 
+	* pdf/ev-poppler.h:
+	* pdf/ev-poppler.cc: New backend.
+	
+	* ps/ps-document.c: (ps_document_init), (ps_document_set_page),
+	(ps_document_get_page), (ps_document_document_iface_init):
+
+	* shell/ev-pixbuf-cache.h:
+	* shell/ev-pixbuf-cache.c: (ev_pixbuf_cache_init),
+	(dispose_cache_job_info), (job_finished_cb), (move_one_job),
+	(ev_pixbuf_cache_update_range), (copy_job_to_job_info),
+	(add_job_if_needed), (ev_pixbuf_cache_set_page_range),
+	(ev_pixbuf_cache_get_pixbuf), (ev_pixbuf_cache_get_link_mapping):
+	Fix up code to grab a page cache per each doc.  Also, fix to be 0
+	based.
+	
+	* shell/ev-sidebar-thumbnails.c:
+	(ev_sidebar_tree_selection_changed), (page_changed_cb),
+	(ev_sidebar_thumbnails_set_document): Fix to be 0 based.
+
+	* shell/ev-view.c: (status_message_from_link),
+	(find_page_at_location), (get_link_at_location),
+	(ev_view_motion_notify_event), (ev_view_button_release_event),
+	(ev_view_init): Use the new link code.  Fix to be 0 based.
+
+	* shell/ev-window.c: (update_action_sensitivity),
+	(document_supports_sidebar): 0 based.
+
 Fri Mar 25 16:55:58 2005  Jonathan Blandford  <jrb redhat com>
 
 	* pdf/pdf-document.cc: Patch from Fernando Herrera
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/Makefile.am,v
retrieving revision 1.12
diff -u -p -r1.12 Makefile.am
--- Makefile.am	3 Mar 2005 10:06:42 -0000	1.12
+++ Makefile.am	31 Mar 2005 07:33:35 -0000
@@ -1,4 +1,4 @@
-SUBDIRS = lib cut-n-paste data backend po pdf ps pixbuf shell thumbnailer
+SUBDIRS = lib cut-n-paste data backend po pdf ps shell thumbnailer
 
 intltool_extra = intltool-extract.in intltool-merge.in intltool-update.in
 
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/evince/configure.ac,v
retrieving revision 1.44
diff -u -p -r1.44 configure.ac
--- configure.ac	16 Mar 2005 13:07:44 -0000	1.44
+++ configure.ac	31 Mar 2005 07:33:35 -0000
@@ -32,12 +32,12 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GET
 
 PKG_CHECK_MODULES(LIBEVPRIVATE, gtk+-2.0 >= 2.4.0)
 PKG_CHECK_MODULES(RECENT_FILES, gtk+-2.0 >= 2.4.0 libgnomeui-2.0 >= 2.4.0)
-PKG_CHECK_MODULES(SHELL, gtk+-2.0 >= 2.6.0 libgnomeui-2.0 gnome-vfs-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libglade-2.0 gconf-2.0 poppler >= 0.1.1)
-PKG_CHECK_MODULES(THUMBNAILER, gtk+-2.0 >= 2.6.0 gnome-vfs-2.0 poppler >= 0.1.1)
+PKG_CHECK_MODULES(SHELL, gtk+-2.0 >= 2.6.0 libgnomeui-2.0 gnome-vfs-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libglade-2.0 gconf-2.0 poppler-glib >= 0.1.1)
+PKG_CHECK_MODULES(THUMBNAILER, gtk+-2.0 >= 2.6.0 gnome-vfs-2.0 poppler-glib >= 0.1.1)
 PKG_CHECK_MODULES(DVI, gtk+-2.0 >= 2.6.0)
 PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6.0)
 PKG_CHECK_MODULES(PS, gtk+-2.0 >= 2.6.0 gnome-vfs-2.0 libgnomeui-2.0)
-PKG_CHECK_MODULES(POPPLER, poppler >= 0.1.1)
+PKG_CHECK_MODULES(POPPLER_GLIB, poppler-glib >= 0.1.2)
 
 GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`  
 AC_SUBST(GLIB_GENMARSHAL)
Index: backend/ev-document-thumbnails.h
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-document-thumbnails.h,v
retrieving revision 1.3
diff -u -p -r1.3 ev-document-thumbnails.h
--- backend/ev-document-thumbnails.h	7 Mar 2005 13:51:11 -0000	1.3
+++ backend/ev-document-thumbnails.h	31 Mar 2005 07:33:35 -0000
@@ -52,6 +52,12 @@ struct _EvDocumentThumbnailsIface
 };
 
 GType      ev_document_thumbnails_get_type       (void);
+
+/* FIXME: This is a little bit busted.  We call get_thumbnail w/ a suggested
+ * width, but we should call it with a scale so that different sized pages get
+ * sized proportionally.
+ */
+
 GdkPixbuf *ev_document_thumbnails_get_thumbnail  (EvDocumentThumbnails *document,
                                                   gint                  page,
                                                   gint                  size,
Index: backend/ev-document.c
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-document.c,v
retrieving revision 1.18
diff -u -p -r1.18 ev-document.c
--- backend/ev-document.c	23 Mar 2005 11:07:31 -0000	1.18
+++ backend/ev-document.c	31 Mar 2005 07:33:35 -0000
@@ -27,17 +27,9 @@
 
 static void ev_document_class_init (gpointer g_class);
 
-enum
-{
-	PAGE_CHANGED,
-	SCALE_CHANGED,
-	LAST_SIGNAL
-};
 
-static guint signals[LAST_SIGNAL] = { 0 };
 GMutex *ev_doc_mutex = NULL;
 
-
 #define LOG(x) 
 GType
 ev_document_get_type (void)
@@ -75,26 +67,6 @@ ev_document_error_quark (void)
 static void
 ev_document_class_init (gpointer g_class)
 {
-	signals[PAGE_CHANGED] =
-		g_signal_new ("page_changed",
-			      EV_TYPE_DOCUMENT,
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EvDocumentIface, page_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE,
-			      0);
-
-	signals[SCALE_CHANGED] =
-		g_signal_new ("scale_changed",
-			      EV_TYPE_DOCUMENT,
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EvDocumentIface, scale_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE,
-			      0);
-
 	g_object_interface_install_property (g_class,
 				g_param_spec_string ("title",
 						     "Document Title",
@@ -140,8 +112,11 @@ ev_document_load (EvDocument  *document,
 	gboolean retval;
 	LOG ("ev_document_load");
 	retval = iface->load (document, uri, error);
+
 	/* Call this to make the initial cached copy */
-	ev_document_get_page_cache (document);
+	if (retval)
+		ev_document_get_page_cache (document);
+
 	return retval;
 }
 
@@ -205,16 +180,6 @@ ev_document_get_page (EvDocument *docume
 }
 
 void
-ev_document_set_target (EvDocument  *document,
-			GdkDrawable *target)
-{
-	EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
-
-	LOG ("ev_document_set_target");
-	iface->set_target (document, target);
-}
-
-void
 ev_document_set_scale (EvDocument   *document,
 		       double        scale)
 {
@@ -225,17 +190,6 @@ ev_document_set_scale (EvDocument   *doc
 }
 
 void
-ev_document_set_page_offset (EvDocument  *document,
-			     int          x,
-			     int          y)
-{
-	EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
-
-	LOG ("ev_document_set_page_offset");
-	iface->set_page_offset (document, x, y);
-}
-
-void
 ev_document_get_page_size   (EvDocument   *document,
 			     int           page,
 			     int          *width,
@@ -269,25 +223,29 @@ ev_document_get_link (EvDocument   *docu
 	EvLink *retval;
 
 	LOG ("ev_document_get_link");
+	if (iface->get_link == NULL)
+		return NULL;
 	retval = iface->get_link (document, x, y);
 
 	return retval;
 }
 
-void
-ev_document_render (EvDocument  *document,
-		    int          clip_x,
-		    int          clip_y,
-		    int          clip_width,
-		    int          clip_height)
+GList *
+ev_document_get_links (EvDocument *document)
 {
 	EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
+	GList *retval;
+
+	LOG ("ev_document_get_link");
+	if (iface->get_links == NULL)
+		return NULL;
+	retval = iface->get_links (document);
 
-	LOG ("ev_document_render");
-	iface->render (document, clip_x, clip_y, clip_width, clip_height);
+	return retval;
 }
 
 
+
 GdkPixbuf *
 ev_document_render_pixbuf (EvDocument *document)
 {
@@ -302,15 +260,3 @@ ev_document_render_pixbuf (EvDocument *d
 	return retval;
 }
 
-
-void
-ev_document_page_changed (EvDocument *document)
-{
-	g_signal_emit (G_OBJECT (document), signals[PAGE_CHANGED], 0);
-}
-
-void
-ev_document_scale_changed (EvDocument *document)
-{
-	g_signal_emit (G_OBJECT (document), signals[SCALE_CHANGED], 0);
-}
Index: backend/ev-document.h
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-document.h,v
retrieving revision 1.17
diff -u -p -r1.17 ev-document.h
--- backend/ev-document.h	23 Mar 2005 11:07:31 -0000	1.17
+++ backend/ev-document.h	31 Mar 2005 07:33:35 -0000
@@ -73,13 +73,8 @@ struct _EvDocumentIface
 	void	    (* set_page)	(EvDocument   *document,
 					 int           page);
 	int	    (* get_page)	(EvDocument   *document);
-	void	    (* set_target)      (EvDocument   *document,
-					 GdkDrawable  *target);
 	void	    (* set_scale)       (EvDocument   *document,
 					 double        scale);
-	void	    (* set_page_offset) (EvDocument   *document,
-					 int           x,
-					 int           y);
 	void	    (* get_page_size)   (EvDocument   *document,
 					 int           page,
 					 int          *width,
@@ -89,15 +84,8 @@ struct _EvDocumentIface
 	EvLink    * (* get_link)	(EvDocument   *document,
 					 int           x,
 					 int	       y);
-	void	    (* render)          (EvDocument   *document,
-					 int           clip_x,
-					 int           clip_y,
-					 int           clip_width,
-					 int           clip_height);
-	GdkPixbuf *(* render_pixbuf)    (EvDocument   *document);
-
-
-
+	GList     * (* get_links)	(EvDocument   *document);
+	GdkPixbuf * (* render_pixbuf)   (EvDocument   *document);
 };
 
 GType        ev_document_get_type       (void);
@@ -106,42 +94,31 @@ EvPageCache *ev_document_get_page_cache 
 GMutex      *ev_document_get_doc_mutex  (void);
 
 
-gboolean ev_document_load            (EvDocument   *document,
-				      const char   *uri,
-				      GError      **error);
-gboolean ev_document_save            (EvDocument   *document,
-				      const char   *uri,
-				      GError      **error);
-char    *ev_document_get_title       (EvDocument   *document);
-int      ev_document_get_n_pages     (EvDocument   *document);
-void     ev_document_set_page        (EvDocument   *document,
-				      int           page);
-int      ev_document_get_page        (EvDocument   *document);
-void     ev_document_set_target      (EvDocument   *document,
-				      GdkDrawable  *target);
-void     ev_document_set_scale       (EvDocument   *document,
-				      double        scale);
-void     ev_document_set_page_offset (EvDocument   *document,
-				      int           x,
-				      int           y);
-void     ev_document_get_page_size   (EvDocument   *document,
-				      int           page,
-				      int          *width,
-				      int          *height);
-char    *ev_document_get_text	     (EvDocument   *document,
-				      GdkRectangle *rect);
-EvLink  *ev_document_get_link	     (EvDocument   *document,
-				      int           x,
-				      int	    y);
-void     ev_document_render          (EvDocument   *document,
-				      int           clip_x,
-				      int           clip_y,
-				      int           clip_width,
-				      int           clip_height);
-/* Quick hack to test threaded rendering */
-GdkPixbuf *ev_document_render_pixbuf   (EvDocument   *document);
-void	 ev_document_page_changed    (EvDocument *document);
-void	 ev_document_scale_changed   (EvDocument *document);
+gboolean   ev_document_load          (EvDocument    *document,
+				      const char    *uri,
+				      GError       **error);
+gboolean   ev_document_save          (EvDocument    *document,
+				      const char    *uri,
+				      GError       **error);
+char      *ev_document_get_title     (EvDocument    *document);
+int        ev_document_get_n_pages   (EvDocument    *document);
+void       ev_document_set_page      (EvDocument    *document,
+				      int            page);
+int        ev_document_get_page      (EvDocument    *document);
+void       ev_document_set_scale     (EvDocument    *document,
+				      double         scale);
+void       ev_document_get_page_size (EvDocument    *document,
+				      int            page,
+				      int           *width,
+				      int           *height);
+char      *ev_document_get_text      (EvDocument    *document,
+				      GdkRectangle  *rect);
+EvLink    *ev_document_get_link      (EvDocument    *document,
+				      int            x,
+				      int            y);
+GList     *ev_document_get_links     (EvDocument    *document);
+GdkPixbuf *ev_document_render_pixbuf (EvDocument    *document);
+
 
 G_END_DECLS
 
Index: backend/ev-jobs.c
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-jobs.c,v
retrieving revision 1.2
diff -u -p -r1.2 ev-jobs.c
--- backend/ev-jobs.c	23 Mar 2005 11:07:31 -0000	1.2
+++ backend/ev-jobs.c	31 Mar 2005 07:33:35 -0000
@@ -182,7 +182,8 @@ ev_job_render_new (EvDocument *document,
 		   gint        page,
 		   double      scale,
 		   gint        width,
-		   gint        height)
+		   gint        height,
+		   gboolean    include_links)
 {
 	EvJobRender *job;
 
@@ -193,6 +194,7 @@ ev_job_render_new (EvDocument *document,
 	job->scale = scale;
 	job->target_width = width;
 	job->target_height = height;
+	job->include_links = include_links;
 
 	return EV_JOB (job);
 }
@@ -204,9 +206,11 @@ ev_job_render_run (EvJobRender *job)
 
 	g_mutex_lock (EV_DOC_MUTEX);
 
-	ev_document_set_scale (EV_JOB (job)->document, job->scale);
 	ev_document_set_page (EV_JOB (job)->document, job->page);
+	ev_document_set_scale (EV_JOB (job)->document, job->scale);
 	job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document);
+	if (job->include_links)
+		job->link_mapping = ev_document_get_links (EV_JOB (job)->document);
 	EV_JOB (job)->finished = TRUE;
 
 	g_mutex_unlock (EV_DOC_MUTEX);
Index: backend/ev-jobs.h
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-jobs.h,v
retrieving revision 1.2
diff -u -p -r1.2 ev-jobs.h
--- backend/ev-jobs.h	23 Mar 2005 11:07:31 -0000	1.2
+++ backend/ev-jobs.h	31 Mar 2005 07:33:35 -0000
@@ -97,6 +97,8 @@ struct _EvJobRender
 	gint target_width;
 	gint target_height;
 	GdkPixbuf *pixbuf;
+	GList *link_mapping;
+	gboolean include_links;
 };
 
 struct _EvJobRenderClass
@@ -134,7 +136,8 @@ EvJob          *ev_job_render_new       
 					   gint            page,
 					   double          scale,
 					   gint            width,
-					   gint            height);
+					   gint            height,
+					   gboolean        include_links);
 void            ev_job_render_run         (EvJobRender    *thumbnail);
 
 /* EvJobThumbnail */
Index: backend/ev-link.c
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-link.c,v
retrieving revision 1.3
diff -u -p -r1.3 ev-link.c
--- backend/ev-link.c	23 Mar 2005 11:07:31 -0000	1.3
+++ backend/ev-link.c	31 Mar 2005 07:33:35 -0000
@@ -85,13 +85,14 @@ void
 ev_link_set_title (EvLink* self, const char *title)
 {
 	g_assert (EV_IS_LINK (self));
-	g_assert (title != NULL);
 
 	if (self->priv->title != NULL) {
 		g_free (self->priv->title);
 	}
-
-	self->priv->title = g_strdup (title);
+	if (title)
+		self->priv->title = g_strdup (title);
+	else
+		self->priv->title = NULL;
 
 	g_object_notify (G_OBJECT (self), "title");
 }
@@ -314,3 +315,50 @@ ev_link_new_external (const char *title,
 				      "type", EV_LINK_TYPE_EXTERNAL_URI,
 				      NULL));
 }
+
+
+
+static void
+ev_link_mapping_free_foreach (EvLinkMapping *mapping)
+{
+	g_object_unref (G_OBJECT (mapping->link));
+	g_free (mapping);
+}
+
+void
+ev_link_mapping_free (GList *link_mapping)
+{
+	if (link_mapping == NULL)
+		return;
+
+	g_list_foreach (link_mapping, (GFunc) (ev_link_mapping_free_foreach), NULL);
+	g_list_free (link_mapping);
+}
+
+
+EvLink *
+ev_link_mapping_find (GList   *link_mapping,
+		      gdouble  x,
+		      gdouble  y)
+{
+	GList *list;
+	EvLink *link = NULL;
+	int i;
+	
+	i = 0;
+	for (list = link_mapping; list; list = list->next) {
+		EvLinkMapping *mapping = list->data;
+
+		i++;
+		if ((x >= mapping->x1) &&
+		    (y >= mapping->y1) &&
+		    (x <= mapping->x2) &&
+		    (y <= mapping->y2)) {
+			link = mapping->link;
+			break;
+		}
+	}
+
+	return link;
+}
+
Index: backend/ev-link.h
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-link.h,v
retrieving revision 1.2
diff -u -p -r1.2 ev-link.h
--- backend/ev-link.h	23 Mar 2005 11:07:31 -0000	1.2
+++ backend/ev-link.h	31 Mar 2005 07:33:35 -0000
@@ -37,6 +37,8 @@ typedef struct _EvLinkPrivate EvLinkPriv
 
 #define EV_TYPE_LINK_TYPE	  (ev_link_type_get_type ())
 
+
+
 typedef enum
 {
 	EV_LINK_TYPE_TITLE,
@@ -67,6 +69,22 @@ int		ev_link_get_page	(EvLink     *link)
 void		ev_link_set_page	(EvLink     *link,
 					 int             page);
 
+/* Link Mapping stuff */
+
+typedef struct _EvLinkMapping	  EvLinkMapping;
+struct _EvLinkMapping
+{
+	EvLink *link;
+	gdouble x1;
+	gdouble y1;
+	gdouble x2;
+	gdouble y2;
+};
+
+void    ev_link_mapping_free (GList   *link_mapping);
+EvLink *ev_link_mapping_find (GList   *link_mapping,
+			      gdouble  x,
+			      gdouble  y);
 G_END_DECLS
 
 #endif /* !EV_LINK_H */
Index: backend/ev-page-cache.c
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-page-cache.c,v
retrieving revision 1.2
diff -u -p -r1.2 ev-page-cache.c
--- backend/ev-page-cache.c	23 Mar 2005 11:07:31 -0000	1.2
+++ backend/ev-page-cache.c	31 Mar 2005 07:33:35 -0000
@@ -48,7 +48,7 @@ G_DEFINE_TYPE (EvPageCache, ev_page_cach
 static void
 ev_page_cache_init (EvPageCache *page_cache)
 {
-	page_cache->current_page = 1;
+	page_cache->current_page = 0;
 }
 
 static void
@@ -102,13 +102,13 @@ _ev_page_cache_new (EvDocument *document
 	page_cache->title = ev_document_get_title (document);
 
 	ev_document_set_scale (document, 1.0);
-	for (i = 1; i <= page_cache->n_pages; i++) {
+	for (i = 0; i < page_cache->n_pages; i++) {
 		gint page_width = 0;
 		gint page_height = 0;
 
 		ev_document_get_page_size (document, i, &page_width, &page_height);
 
-		if (i == 1) {
+		if (i == 0) {
 			page_cache->uniform_width = page_width;
 			page_cache->uniform_height = page_height;
 		} else if (page_cache->uniform &&
@@ -169,7 +169,7 @@ ev_page_cache_set_current_page (EvPageCa
 				int          page)
 {
 	g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
-	g_return_if_fail (page > 0 || page <= page_cache->n_pages);
+	g_return_if_fail (page >= 0 || page < page_cache->n_pages);
 
 	if (page == page_cache->current_page)
 		return;
@@ -204,7 +204,7 @@ ev_page_cache_get_size (EvPageCache *pag
 			gint        *height)
 {
 	g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
-	g_return_if_fail (page > 0 && page <= page_cache->n_pages);
+	g_return_if_fail (page >= 0 && page < page_cache->n_pages);
 
 	if (page_cache->uniform) {
 		if (width)
@@ -214,7 +214,7 @@ ev_page_cache_get_size (EvPageCache *pag
 	} else {
 		EvPageCacheInfo *info;
 
-		info = &(page_cache->size_cache [page - 1]);
+		info = &(page_cache->size_cache [page]);
 		
 		if (width)
 			*width = info->width;
@@ -234,7 +234,7 @@ ev_page_cache_next_page (EvPageCache *pa
 {
 	g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
 
-	if (page_cache->current_page >= page_cache->n_pages)
+	if (page_cache->current_page > page_cache->n_pages)
 		return FALSE;
 
 	ev_page_cache_set_current_page (page_cache, page_cache->current_page + 1);
@@ -247,7 +247,7 @@ ev_page_cache_prev_page (EvPageCache *pa
 {
 	g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
 
-	if (page_cache->current_page <= 1)
+	if (page_cache->current_page <= 0)
 		return FALSE;
 
 	ev_page_cache_set_current_page (page_cache, page_cache->current_page - 1);
Index: pdf/Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/pdf/Makefile.am,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile.am
--- pdf/Makefile.am	1 Mar 2005 22:24:08 -0000	1.2
+++ pdf/Makefile.am	31 Mar 2005 07:33:35 -0000
@@ -1,24 +1,16 @@
 INCLUDES =					\
 	-I$(top_srcdir)				\
 	-I$(top_srcdir)/backend			\
-	$(POPPLER_CFLAGS)			\
+	$(POPPLER_GLIB_CFLAGS)			\
 	$(GTK_CFLAGS)				\
 	-DDATADIR=\""$(datadir)"\"
 
-noinst_PROGRAMS = test-gdk-output-dev
-
 noinst_LTLIBRARIES = libpdfdocument.la
 
 libpdfdocument_la_SOURCES =			\
-	GDKSplashOutputDev.cc			\
-	GDKSplashOutputDev.h			\
-	Thumb.cc				\
-	Thumb.h					\
-	pdf-document.cc				\
-	pdf-document.h
+	ev-poppler.cc				\
+	ev-poppler.h
 
-test_gdk_output_dev_SOURCES =			\
-       test-gdk-output-dev.cc
 
 test_gdk_output_dev_LDADD =			\
 	libpdfdocument.la			\
Index: pdf/ev-poppler.cc
===================================================================
RCS file: pdf/ev-poppler.cc
diff -N pdf/ev-poppler.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pdf/ev-poppler.cc	31 Mar 2005 07:33:36 -0000
@@ -0,0 +1,592 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
+/* pdfdocument.h: Implementation of EvDocument for PDF
+ * Copyright (C) 2004, Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 <gtk/gtk.h>
+#include <poppler.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+
+#include "ev-poppler.h"
+#include "ev-ps-exporter.h"
+#include "ev-document-find.h"
+#include "ev-document-misc.h"
+#include "ev-document-links.h"
+#include "ev-document-security.h"
+#include "ev-document-thumbnails.h"
+
+
+enum {
+	PROP_0,
+	PROP_TITLE
+};
+
+
+struct _PdfDocumentClass
+{
+	GObjectClass parent_class;
+};
+
+struct _PdfDocument
+{
+	GObject parent_instance;
+
+	PopplerDocument *document;
+	PopplerPage *page;
+	double scale;
+	gchar *password;
+};
+
+static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
+static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
+static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
+static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
+static void pdf_document_thumbnails_get_dimensions      (EvDocumentThumbnails      *document_thumbnails,
+							 gint                       page,
+							 gint                       size,
+							 gint                      *width,
+							 gint                      *height);
+static EvLink * ev_link_from_action (PopplerAction *action);
+
+
+G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
+                         {
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
+							pdf_document_document_iface_init);
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
+							pdf_document_security_iface_init);
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+							pdf_document_document_thumbnails_iface_init);
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
+							pdf_document_document_links_iface_init);
+#if 0
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER,
+							pdf_document_ps_exporter_iface_init);
+				 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
+							pdf_document_find_iface_init);
+#endif
+			 });
+
+
+
+
+
+
+static void
+pdf_document_get_property (GObject *object,
+		           guint prop_id,
+		           GValue *value,
+		           GParamSpec *pspec)
+{
+	PdfDocument *pdf_document = PDF_DOCUMENT (object);
+
+	switch (prop_id)
+	{
+		case PROP_TITLE:
+			if (pdf_document->document == NULL)
+				g_value_set_string (value, NULL);
+			else
+				g_object_get_property (G_OBJECT (pdf_document->document), "title", value);
+			break;
+	}
+}
+
+static void
+pdf_document_class_init (PdfDocumentClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->get_property = pdf_document_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_TITLE, "title");
+}
+
+static void
+pdf_document_init (PdfDocument *pdf_document)
+{
+	pdf_document->page = NULL;
+	pdf_document->scale = 1.0;
+	pdf_document->password = NULL;
+}
+
+static void
+convert_error (GError  *poppler_error,
+	       GError **error)
+{
+	if (poppler_error == NULL)
+		return;
+
+	if (poppler_error->domain == POPPLER_ERROR) {
+		/* convert poppler errors into EvDocument errors */
+		gint code = EV_DOCUMENT_ERROR_INVALID;
+		if (poppler_error->code == POPPLER_ERROR_INVALID)
+			code = EV_DOCUMENT_ERROR_INVALID;
+		else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED)
+			code = EV_DOCUMENT_ERROR_ENCRYPTED;
+			
+
+		g_set_error (error,
+			     EV_DOCUMENT_ERROR,
+			     code,
+			     poppler_error->message,
+			     NULL);
+	} else {
+		g_propagate_error (error, poppler_error);
+	}
+}
+
+
+/* EvDocument */
+static gboolean
+pdf_document_save (EvDocument  *document,
+		   const char  *uri,
+		   GError     **error)
+{
+	gboolean retval;
+	GError *poppler_error = NULL;
+
+	retval = poppler_document_save (PDF_DOCUMENT (document)->document,
+					uri,
+					&poppler_error);
+	if (! retval)
+		convert_error (poppler_error, error);
+
+	return retval;
+}
+
+static gboolean
+pdf_document_load (EvDocument   *document,
+		   const char   *uri,
+		   GError      **error)
+{
+	GError *poppler_error = NULL;
+	PdfDocument *pdf_document = PDF_DOCUMENT (document);
+
+	pdf_document->document =
+		poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
+
+	if (pdf_document->document == NULL) {
+		convert_error (poppler_error, error);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int
+pdf_document_get_n_pages (EvDocument *document)
+{
+	return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
+}
+
+static void
+pdf_document_set_page (EvDocument   *document,
+		       int           page)
+{
+	page = CLAMP (page, 0, poppler_document_get_n_pages (PDF_DOCUMENT (document)->document) - 1);
+
+	PDF_DOCUMENT (document)->page = poppler_document_get_page (PDF_DOCUMENT (document)->document, page);
+}
+
+static int
+pdf_document_get_page (EvDocument   *document)
+{
+	PdfDocument *pdf_document;
+
+	pdf_document = PDF_DOCUMENT (document);
+
+	if (pdf_document->page)
+		return poppler_page_get_index (pdf_document->page);
+
+	return 1;
+}
+
+static void 
+pdf_document_set_scale (EvDocument   *document,
+			double        scale)
+{
+	PDF_DOCUMENT (document)->scale = scale;
+}
+
+
+static void
+get_size_from_page (PopplerPage *poppler_page,
+		    double       scale,
+		    int         *width,
+		    int         *height)
+{
+	gdouble width_d, height_d;
+	poppler_page_get_size (poppler_page, &width_d, &height_d);
+	if (width)
+		*width = (int) (width_d * scale);
+	if (height)
+		*height = (int) (height_d * scale);
+
+}
+
+static void
+pdf_document_get_page_size (EvDocument   *document,
+			    int           page,
+			    int          *width,
+			    int          *height)
+{
+	PopplerPage *poppler_page = NULL;
+
+	if (page == -1)
+		poppler_page = PDF_DOCUMENT (document)->page;
+	else
+		poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document,
+							  page);
+
+	if (poppler_page == NULL)
+		poppler_document_get_page (PDF_DOCUMENT (document)->document, 0);
+
+	get_size_from_page (poppler_page,
+			    PDF_DOCUMENT (document)->scale,
+			    width, height);
+}
+
+static GList *
+pdf_document_get_links (EvDocument *document)
+{
+	PdfDocument *pdf_document;
+	GList *retval = NULL;
+	GList *mapping_list;
+	GList *list;
+	gint height;
+
+	pdf_document = PDF_DOCUMENT (document);
+	g_return_val_if_fail (pdf_document->page != NULL, NULL);
+
+	mapping_list = poppler_page_get_link_mapping (pdf_document->page);
+	get_size_from_page (pdf_document->page, 1.0, NULL, &height);
+
+	for (list = mapping_list; list; list = list->next) {
+		PopplerLinkMapping *link_mapping;
+		EvLinkMapping *ev_link_mapping;
+
+		link_mapping = (PopplerLinkMapping *)list->data;
+		ev_link_mapping = g_new (EvLinkMapping, 1);
+		ev_link_mapping->link = ev_link_from_action (link_mapping->action);
+		ev_link_mapping->x1 = link_mapping->x1;
+		ev_link_mapping->x2 = link_mapping->x2;
+		/* Invert this for X-style coordinates */
+		ev_link_mapping->y1 = height - link_mapping->y2;
+		ev_link_mapping->y2 = height - link_mapping->y1;
+
+		retval = g_list_prepend (retval, ev_link_mapping);
+	}
+
+	poppler_page_free_link_mapping (mapping_list);
+
+	return g_list_reverse (retval);
+}
+			
+
+static GdkPixbuf *
+pdf_document_render_pixbuf (EvDocument   *document)
+{
+	PdfDocument *pdf_document;
+	GdkPixbuf *pixbuf;
+	gint width, height;
+
+	pdf_document = PDF_DOCUMENT (document);
+	g_return_val_if_fail (pdf_document->page != NULL, NULL);
+
+	get_size_from_page (pdf_document->page,
+			    pdf_document->scale,
+			    &width, &height);
+
+	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+				 FALSE, 8,
+				 width, height);
+
+	poppler_page_render_to_pixbuf (pdf_document->page,
+				       0, 0,
+				       width, height,
+				       pdf_document->scale,
+				       pixbuf,
+				       0, 0);
+
+	return pixbuf;
+}
+
+/* EvDocumentSecurity */
+
+static gboolean
+pdf_document_has_document_security (EvDocumentSecurity *document_security)
+{
+	/* FIXME: do we really need to have this? */
+	return FALSE;
+}
+
+static void
+pdf_document_set_password (EvDocumentSecurity *document_security,
+			   const char         *password)
+{
+	PdfDocument *document = PDF_DOCUMENT (document_security);
+
+	if (document->password)
+		g_free (document->password);
+
+	document->password = g_strdup (password);
+}
+
+
+
+static void
+pdf_document_document_iface_init (EvDocumentIface *iface)
+{
+	iface->save = pdf_document_save;
+	iface->load = pdf_document_load;
+	iface->get_n_pages = pdf_document_get_n_pages;
+	iface->set_page = pdf_document_set_page;
+	iface->get_page = pdf_document_get_page;
+	iface->set_scale = pdf_document_set_scale;
+	iface->get_page_size = pdf_document_get_page_size;
+	iface->get_links = pdf_document_get_links;
+	iface->render_pixbuf = pdf_document_render_pixbuf;
+};
+
+static void
+pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
+{
+	iface->has_document_security = pdf_document_has_document_security;
+	iface->set_password = pdf_document_set_password;
+}
+
+static gboolean
+pdf_document_links_has_document_links (EvDocumentLinks *document_links)
+{
+	PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
+	PopplerIndexIter *iter;
+
+	g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
+
+	iter = poppler_index_iter_new (pdf_document->document);
+	if (iter == NULL)
+		return FALSE;
+	poppler_index_iter_free (iter);
+
+	return TRUE;
+}
+
+static EvLink *
+ev_link_from_action (PopplerAction *action)
+{
+	EvLink *link;
+	const char *title;
+
+	title = action->any.title;
+	
+	if (action->type == POPPLER_ACTION_GOTO_DEST) {
+		link = ev_link_new_page (title, action->goto_dest.dest->page_num - 1);
+	} else if (action->type == POPPLER_ACTION_URI) {
+		link = ev_link_new_external (title, action->uri.uri);
+	} else {
+		link = ev_link_new_title (title);
+	}
+
+	return link;	
+}
+
+
+static void
+build_tree (PdfDocument      *pdf_document,
+	    GtkTreeModel     *model,
+	    GtkTreeIter      *parent,
+	    PopplerIndexIter *iter)
+{
+
+	do {
+		GtkTreeIter tree_iter;
+		PopplerIndexIter *child;
+		PopplerAction *action;
+		EvLink *link;
+		
+		action = poppler_index_iter_get_action (iter);
+		if (action) {
+			gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
+			link = ev_link_from_action (action);
+			poppler_action_free (action);
+
+			gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
+					    EV_DOCUMENT_LINKS_COLUMN_MARKUP, ev_link_get_title (link),
+					    EV_DOCUMENT_LINKS_COLUMN_LINK, link,
+					    -1);
+			child = poppler_index_iter_get_child (iter);
+			if (child)
+				build_tree (pdf_document, model, &tree_iter, child);
+			poppler_index_iter_free (child);
+		}
+	} while (poppler_index_iter_next (iter));
+}
+
+
+static GtkTreeModel *
+pdf_document_links_get_links_model (EvDocumentLinks *document_links)
+{
+	PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
+	GtkTreeModel *model = NULL;
+	PopplerIndexIter *iter;
+
+	g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
+
+	iter = poppler_index_iter_new (pdf_document->document);
+	/* Create the model iff we have items*/
+	if (iter != NULL) {
+		model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
+							     G_TYPE_STRING,
+							     G_TYPE_POINTER);
+		build_tree (pdf_document, model, NULL, iter);
+		poppler_index_iter_free (iter);
+	}
+	
+
+	return model;
+}
+
+
+static void
+pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
+{
+	iface->has_document_links = pdf_document_links_has_document_links;
+	iface->get_links_model = pdf_document_links_get_links_model;
+}
+
+
+static GdkPixbuf *
+make_thumbnail_for_size (PdfDocument *pdf_document,
+			 gint         page,
+			 gint         size,
+			 gboolean     border)
+{
+	PopplerPage *poppler_page;
+	GdkPixbuf *pixbuf;
+	int width, height;
+	int x_offset, y_offset;
+	double scale;
+	gdouble unscaled_width, unscaled_height;
+
+	poppler_page = poppler_document_get_page (pdf_document->document, page);
+
+	g_return_val_if_fail (poppler_page != NULL, NULL);
+
+	pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document), page, size, &width, &height);
+	poppler_page_get_size (poppler_page, &unscaled_width, &unscaled_height);
+	scale = width / unscaled_width;
+
+	if (border) {
+		pixbuf = ev_document_misc_get_thumbnail_frame (width, height, NULL);
+		x_offset = 1;
+		y_offset = 1;
+	} else {
+		pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+					 width, height);
+		gdk_pixbuf_fill (pixbuf, 0xffffffff);
+		x_offset = 0;
+		y_offset = 0;
+	}
+
+	poppler_page_render_to_pixbuf (poppler_page, 0, 0,
+				       width, height,
+				       scale, pixbuf,
+				       x_offset, y_offset);
+
+	return pixbuf;
+}
+
+static GdkPixbuf *
+pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
+	 			       gint 		     page,
+ 				       gint                  size,
+		 		       gboolean              border)
+{
+	PdfDocument *pdf_document;
+	PopplerPage *poppler_page;
+	GdkPixbuf *pixbuf;
+
+	pdf_document = PDF_DOCUMENT (document_thumbnails);
+
+	poppler_page = poppler_document_get_page (pdf_document->document, page);
+	g_return_val_if_fail (poppler_page != NULL, NULL);
+
+	pixbuf = poppler_page_get_thumbnail (poppler_page);
+	if (pixbuf != NULL) {
+		/* The document provides its own thumbnails. */
+		if (border) {
+			GdkPixbuf *real_pixbuf;
+
+			real_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
+			g_object_unref (pixbuf);
+			pixbuf = real_pixbuf;
+		}
+	} else {
+		/* There is no provided thumbnail.  We need to make one. */
+		pixbuf = make_thumbnail_for_size (pdf_document, page, size, border);
+	}
+	return pixbuf;
+}
+
+static void
+pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
+					gint                  page,
+					gint                  size,
+					gint                 *width,
+					gint                 *height)
+{
+	PdfDocument *pdf_document;
+	PopplerPage *poppler_page;
+	gint has_thumb;
+	
+	pdf_document = PDF_DOCUMENT (document_thumbnails);
+	poppler_page = poppler_document_get_page (pdf_document->document, page);
+
+	g_return_if_fail (width != NULL);
+	g_return_if_fail (height != NULL);
+	g_return_if_fail (poppler_page != NULL);
+
+	has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
+
+	if (!has_thumb) {
+		int page_width, page_height;
+
+		get_size_from_page (poppler_page, 1.0, &page_width, &page_height);
+
+		if (page_width > page_height) {
+			*width = size;
+			*height = (int) (size * page_height / page_width);
+		} else {
+			*width = (int) (size * page_width / page_height);
+			*height = size;
+		}
+	}
+}
+
+static void
+pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
+{
+	iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
+	iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
+}
+
+PdfDocument *
+pdf_document_new (void)
+{
+	return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
+}
Index: pdf/ev-poppler.h
===================================================================
RCS file: pdf/ev-poppler.h
diff -N pdf/ev-poppler.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pdf/ev-poppler.h	31 Mar 2005 07:33:36 -0000
@@ -0,0 +1,39 @@
+/* pdfdocument.h: Implementation of EvDocument for PDF
+ * Copyright (C) 2004, Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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.
+ */
+
+#ifndef __PDF_DOCUMENT_H__
+#define __PDF_DOCUMENT_H__
+
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+#define PDF_TYPE_DOCUMENT             (pdf_document_get_type ())
+#define PDF_DOCUMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), PDF_TYPE_DOCUMENT, PdfDocument))
+#define PDF_IS_DOCUMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PDF_TYPE_DOCUMENT))
+
+typedef struct _PdfDocument PdfDocument;
+typedef struct _PdfDocumentClass PdfDocumentClass;
+
+PdfDocument *pdf_document_new       (void);
+GType        pdf_document_get_type  (void) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* __PDF_DOCUMENT_H__ */
Index: ps/ps-document.c
===================================================================
RCS file: /cvs/gnome/evince/ps/ps-document.c,v
retrieving revision 1.24
diff -u -p -r1.24 ps-document.c
--- ps/ps-document.c	23 Mar 2005 11:07:31 -0000	1.24
+++ ps/ps-document.c	31 Mar 2005 07:33:36 -0000
@@ -137,8 +137,6 @@ ps_document_init (PSDocument *gs)
 	gs->bytes_left = 0;
 	gs->buffer_bytes_left = 0;
 
-	gs->page_x_offset = 0;
-	gs->page_y_offset = 0;
 	gs->zoom_factor = 1.0;
 
 	gs->gs_status = _("No document loaded.");
@@ -1208,7 +1206,7 @@ ps_document_set_page (EvDocument  *docum
 
 	LOG ("Set document page %d\n", page);
 
-	gs->current_page = page - 1;
+	gs->current_page = page;
 	compute_dimensions (gs, page);
 }
 
@@ -1219,7 +1217,7 @@ ps_document_get_page (EvDocument  *docum
 
 	g_return_val_if_fail (ps != NULL, -1);
 
-	return ps->current_page + 1;
+	return ps->current_page;
 }
 
 static void
@@ -1233,17 +1231,6 @@ ps_document_set_scale (EvDocument  *docu
 }
 
 static void
-ps_document_set_page_offset (EvDocument  *document,
-			      int          x,
-			      int          y)
-{
-	PSDocument *gs = PS_DOCUMENT (document);
-
-	gs->page_x_offset = x;
-	gs->page_y_offset = y;
-}
-
-static void
 ps_document_get_page_size (EvDocument   *document,
 			   int           page,
 			   int          *width,
@@ -1338,7 +1325,6 @@ ps_document_document_iface_init (EvDocum
 	iface->set_page = ps_document_set_page;
 	iface->get_page = ps_document_get_page;
 	iface->set_scale = ps_document_set_scale;
-	iface->set_page_offset = ps_document_set_page_offset;
 	iface->get_page_size = ps_document_get_page_size;
 	iface->render_pixbuf = ps_document_render_pixbuf;
 }
Index: shell/ev-pixbuf-cache.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.c,v
retrieving revision 1.2
diff -u -p -r1.2 ev-pixbuf-cache.c
--- shell/ev-pixbuf-cache.c	23 Mar 2005 11:07:32 -0000	1.2
+++ shell/ev-pixbuf-cache.c	31 Mar 2005 07:33:36 -0000
@@ -6,6 +6,7 @@ typedef struct _CacheJobInfo
 {
 	EvJob *job;
 	GdkPixbuf *pixbuf;
+	GList *link_mapping;
 } CacheJobInfo;
 
 struct _EvPixbufCache
@@ -50,14 +51,16 @@ static void          job_finished_cb    
 						 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);
 
 
 /* These are used for iterating through the prev and next arrays */
 #define FIRST_VISABLE_PREV(pixbuf_cache) \
 	(MAX (0, pixbuf_cache->preload_cache_size + 1 - pixbuf_cache->start_page))
 #define VISIBLE_NEXT_LEN(pixbuf_cache, page_cache) \
-	(MIN(pixbuf_cache->preload_cache_size, ev_page_cache_get_n_pages (page_cache) - pixbuf_cache->end_page))
+	(MIN(pixbuf_cache->preload_cache_size, ev_page_cache_get_n_pages (page_cache) - (1 + pixbuf_cache->end_page)))
 #define PAGE_CACHE_LEN(pixbuf_cache) \
 	((pixbuf_cache->end_page - pixbuf_cache->start_page) + 1)
 
@@ -66,8 +69,8 @@ G_DEFINE_TYPE (EvPixbufCache, ev_pixbuf_
 static void
 ev_pixbuf_cache_init (EvPixbufCache *pixbuf_cache)
 {
-	pixbuf_cache->start_page = 1;
-	pixbuf_cache->end_page = 1;
+	pixbuf_cache->start_page = 0;
+	pixbuf_cache->end_page = 0;
 	pixbuf_cache->job_list = g_new0 (CacheJobInfo, PAGE_CACHE_LEN (pixbuf_cache));
 
 	pixbuf_cache->preload_cache_size = 1;
@@ -123,6 +126,10 @@ dispose_cache_job_info (CacheJobInfo *jo
 		g_object_unref (G_OBJECT (job_info->pixbuf));
 		job_info->pixbuf = NULL;
 	}
+	if (job_info->link_mapping) {
+		ev_link_mapping_free (job_info->link_mapping);
+		job_info->link_mapping = NULL;
+	}
 }
 
 static void
@@ -177,6 +184,12 @@ job_finished_cb (EvJob         *job,
 		g_object_unref (job_info->pixbuf);
 	job_info->pixbuf = pixbuf;
 
+	if (job_render->link_mapping) {
+		if (job_info->link_mapping)
+			ev_link_mapping_free (job_info->link_mapping);
+		job_info->link_mapping = job_render->link_mapping;
+	}
+	
 	if (job_info->job == job)
 		job_info->job = NULL;
 	g_object_unref (job);
@@ -268,6 +281,7 @@ move_one_job (CacheJobInfo  *job_info,
 	*target_page = *job_info;
 	job_info->job = NULL;
 	job_info->pixbuf = NULL;
+	job_info->link_mapping = NULL;
 
 	if (new_priority != priority && target_page->job) {
 		g_print ("FIXME: update priority \n");
@@ -303,7 +317,7 @@ ev_pixbuf_cache_update_range (EvPixbufCa
 	/* Start with the prev cache. */
 	page = pixbuf_cache->start_page - pixbuf_cache->preload_cache_size;
 	for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
-		if (page < 1) {
+		if (page < 0) {
 			dispose_cache_job_info (pixbuf_cache->prev_job + i, pixbuf_cache);
 		} else {
 			move_one_job (pixbuf_cache->prev_job + i,
@@ -324,7 +338,7 @@ ev_pixbuf_cache_update_range (EvPixbufCa
 	}
 
 	for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
-		if (page > ev_page_cache_get_n_pages (page_cache)) {
+		if (page >= ev_page_cache_get_n_pages (page_cache)) {
 			dispose_cache_job_info (pixbuf_cache->next_job + i, pixbuf_cache);
 		} else {
 			move_one_job (pixbuf_cache->next_job + i,
@@ -347,6 +361,22 @@ ev_pixbuf_cache_update_range (EvPixbufCa
 	pixbuf_cache->end_page = end_page;
 }
 
+static void
+copy_job_to_job_info (EvJobRender   *job_render,
+		      CacheJobInfo  *job_info,
+		      EvPixbufCache *pixbuf_cache)
+{
+	GdkPixbuf *pixbuf;
+
+	pixbuf = g_object_ref (job_render->pixbuf);
+
+	dispose_cache_job_info (job_info, pixbuf_cache);
+
+	job_info->pixbuf = pixbuf;
+	if (job_render->link_mapping)
+		job_info->link_mapping = job_render->link_mapping;
+}
+
 static CacheJobInfo *
 find_job_cache (EvPixbufCache *pixbuf_cache,
 		int            page)
@@ -426,7 +456,8 @@ add_job_if_needed (EvPixbufCache *pixbuf
 	/* make a new job now */
 	job_info->job = ev_job_render_new (pixbuf_cache->document,
 					   page, scale,
-					   width, height);
+					   width, height,
+					   (job_info->link_mapping == NULL)?TRUE:FALSE);
 	ev_job_queue_add_job (job_info->job, priority);
 	g_signal_connect (job_info->job, "finished", G_CALLBACK (job_finished_cb), pixbuf_cache);
 }
@@ -484,8 +515,8 @@ ev_pixbuf_cache_set_page_range (EvPixbuf
 
 	page_cache = ev_document_get_page_cache (pixbuf_cache->document);
 
-	g_return_if_fail (start_page > 0 && start_page <= ev_page_cache_get_n_pages (page_cache));
-	g_return_if_fail (end_page > 0 && end_page <= ev_page_cache_get_n_pages (page_cache));
+	g_return_if_fail (start_page >= 0 && start_page < ev_page_cache_get_n_pages (page_cache));
+	g_return_if_fail (end_page >= 0 && end_page < ev_page_cache_get_n_pages (page_cache));
 	g_return_if_fail (end_page >= start_page);
 
 	/* First, resize the page_range as needed.  We cull old pages
@@ -514,12 +545,27 @@ ev_pixbuf_cache_get_pixbuf (EvPixbufCach
 	/* We don't need to wait for the idle to handle the callback */
 	if (job_info->job &&
 	    EV_JOB (job_info->job)->finished) {
-		GdkPixbuf *pixbuf;
-
-		pixbuf = g_object_ref (EV_JOB_RENDER (job_info->job)->pixbuf);
-		dispose_cache_job_info (job_info, pixbuf_cache);
-		job_info->pixbuf = pixbuf;
+		copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache);
 	}
 
 	return job_info->pixbuf;
+}
+
+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;
 }
Index: shell/ev-pixbuf-cache.h
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.h,v
retrieving revision 1.2
diff -u -p -r1.2 ev-pixbuf-cache.h
--- shell/ev-pixbuf-cache.h	23 Mar 2005 11:07:32 -0000	1.2
+++ shell/ev-pixbuf-cache.h	31 Mar 2005 07:33:36 -0000
@@ -37,14 +37,17 @@ G_BEGIN_DECLS
 typedef struct _EvPixbufCache       EvPixbufCache;
 typedef struct _EvPixbufCacheClass  EvPixbufCacheClass;
 
-GType          ev_pixbuf_cache_get_type       (void) G_GNUC_CONST;
-EvPixbufCache *ev_pixbuf_cache_new            (EvDocument    *document);
-void           ev_pixbuf_cache_set_page_range (EvPixbufCache *pixbuf_cache,
-					       gint           start_page,
-					       gint           end_page,
-					       gfloat         scale);
-GdkPixbuf     *ev_pixbuf_cache_get_pixbuf     (EvPixbufCache *pixbuf_cache,
-					       gint           page);
+GType          ev_pixbuf_cache_get_type         (void) G_GNUC_CONST;
+EvPixbufCache *ev_pixbuf_cache_new              (EvDocument    *document);
+void           ev_pixbuf_cache_set_page_range   (EvPixbufCache *pixbuf_cache,
+						 gint           start_page,
+						 gint           end_page,
+						 gfloat         scale);
+GdkPixbuf     *ev_pixbuf_cache_get_pixbuf       (EvPixbufCache *pixbuf_cache,
+						 gint           page);
+GList         *ev_pixbuf_cache_get_link_mapping (EvPixbufCache *pixbuf_cache,
+						 gint           page);
+
 
 G_END_DECLS
 
Index: shell/ev-sidebar-thumbnails.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-sidebar-thumbnails.c,v
retrieving revision 1.21
diff -u -p -r1.21 ev-sidebar-thumbnails.c
--- shell/ev-sidebar-thumbnails.c	23 Mar 2005 11:07:32 -0000	1.21
+++ shell/ev-sidebar-thumbnails.c	31 Mar 2005 07:33:36 -0000
@@ -118,7 +118,7 @@ ev_sidebar_tree_selection_changed (GtkTr
 
 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->list_store),
 					&iter);
-	page = gtk_tree_path_get_indices (path)[0] + 1;
+	page = gtk_tree_path_get_indices (path)[0];
 	gtk_tree_path_free (path);
 
 	page_cache = ev_document_get_page_cache (priv->document);
@@ -189,7 +189,7 @@ page_changed_cb (EvPageCache         *pa
 	GtkTreePath *path;
 	GtkTreeSelection *selection;
 
-	path = gtk_tree_path_new_from_indices (page - 1, -1);
+	path = gtk_tree_path_new_from_indices (page, -1);
 	selection = gtk_tree_view_get_selection
 			(GTK_TREE_VIEW (sidebar->priv->tree_view));
 
@@ -247,12 +247,12 @@ ev_sidebar_thumbnails_set_document (EvSi
 	loading_icon = ev_document_misc_get_thumbnail_frame (width, height, NULL);
 
 	gtk_list_store_clear (priv->list_store);
-	for (i = 1; i <= n_pages; i++) {
+	for (i = 0; i < n_pages; i++) {
 		EvJob *job;
 
 		/* FIXME: Bah.  This is still -1 for some reason.  Need to track it down.. */
-		job = ev_job_thumbnail_new (priv->document, i - 1, THUMBNAIL_WIDTH);
-		page = g_strdup_printf ("<i>%d</i>", i);
+		job = ev_job_thumbnail_new (priv->document, i, THUMBNAIL_WIDTH);
+		page = g_strdup_printf ("<i>%d</i>", i + 1); /* FIXME: replace with string. */
 		gtk_list_store_append (priv->list_store, &iter);
 		gtk_list_store_set (priv->list_store, &iter,
 				    COLUMN_PAGE_STRING, page,
Index: shell/ev-view.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-view.c,v
retrieving revision 1.65
diff -u -p -r1.65 ev-view.c
--- shell/ev-view.c	23 Mar 2005 11:07:32 -0000	1.65
+++ shell/ev-view.c	31 Mar 2005 07:33:37 -0000
@@ -704,14 +704,15 @@ static char *
 status_message_from_link (EvLink *link)
 {
 	EvLinkType type;
-	char *msg;
+	char *msg = NULL;
 	int page;
 
 	type = ev_link_get_link_type (link);
 	
 	switch (type) {
 		case EV_LINK_TYPE_TITLE:
-			msg = g_strdup (ev_link_get_title (link));
+			if (ev_link_get_title (link))
+				msg = g_strdup (ev_link_get_title (link));
 			break;
 		case EV_LINK_TYPE_PAGE:
 			page = ev_link_get_page (link);
@@ -721,7 +722,7 @@ status_message_from_link (EvLink *link)
 			msg = g_strdup (ev_link_get_uri (link));
 			break;
 		default:
-			msg = NULL;
+			break;
 	}
 
 	return msg;
@@ -799,6 +800,56 @@ ev_view_set_cursor (EvView *view, EvView
 	}
 }
 
+
+static void
+find_page_at_location (EvView  *view,
+		       gdouble  x,
+		       gdouble  y,
+		       gint    *page,
+		       gint    *x_offset,
+		       gint    *y_offset)
+{
+	GtkBorder border;
+	gint width, height;
+
+	ev_page_cache_get_size (view->page_cache,
+				view->current_page,
+				view->scale,
+				&width, &height);
+	ev_document_misc_get_page_border_size (width, height, &border);
+
+	x -= (border.left + view->spacing);
+	y -= (border.top + view->spacing);
+
+	if ((x < 0) || (y < 0) ||
+	    (x >= width) || (y >= height)) {
+		*page = -1;
+		return;
+	}
+	*page = view->current_page;
+	*x_offset = (gint) x;
+	*y_offset = (gint) y;
+}
+
+static EvLink *
+get_link_at_location (EvView  *view,
+		      gdouble  x,
+		      gdouble  y)
+{
+	gint page;
+	gint x_offset, y_offset;
+	GList *link_mapping;
+
+	find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
+	if (page == -1)
+		return NULL;
+
+	link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
+
+	return ev_link_mapping_find (link_mapping, x_offset /view->scale, y_offset /view->scale);
+}
+
+
 static gboolean
 ev_view_motion_notify_event (GtkWidget      *widget,
 			     GdkEventMotion *event)
@@ -816,13 +867,10 @@ ev_view_motion_notify_event (GtkWidget  
 		view_rect_to_doc_rect (view, &selection, &view->selection);
 
 		gtk_widget_queue_draw (widget);
-	} else if (FALSE && view->document) {
+	} else if (view->document) {
 		EvLink *link;
 
-		g_mutex_lock (EV_DOC_MUTEX);
-		link = ev_document_get_link (view->document, event->x, event->y);
-		g_mutex_unlock (EV_DOC_MUTEX);
-
+		link = get_link_at_location (view, event->x, event->y);
                 if (link) {
 			char *msg;
 
@@ -830,8 +878,6 @@ ev_view_motion_notify_event (GtkWidget  
 			ev_view_set_status (view, msg);
 			ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
 			g_free (msg);
-
-                        g_object_unref (link);
 		} else {
 			ev_view_set_status (view, NULL);
 			if (view->cursor == EV_VIEW_CURSOR_LINK) {
@@ -856,14 +902,9 @@ ev_view_button_release_event (GtkWidget 
 	} else if (view->document) {
 		EvLink *link;
 
-		g_mutex_lock (EV_DOC_MUTEX);
-		link = ev_document_get_link (view->document,
-					     event->x,
-					     event->y);
-		g_mutex_unlock (EV_DOC_MUTEX);
+		link = get_link_at_location (view, event->x, event->y);
 		if (link) {
 			ev_view_go_to_link (view, link);
-			g_object_unref (link);
 		}
 	}
 
@@ -1089,7 +1130,7 @@ ev_view_init (EvView *view)
 
 	view->spacing = 10;
 	view->scale = 1.0;
-	view->current_page = 1;
+	view->current_page = 0;
 	view->pressed_button = -1;
 	view->cursor = EV_VIEW_CURSOR_NORMAL;
 }
Index: shell/ev-window.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-window.c,v
retrieving revision 1.83
diff -u -p -r1.83 ev-window.c
--- shell/ev-window.c	23 Mar 2005 11:07:32 -0000	1.83
+++ shell/ev-window.c	31 Mar 2005 07:33:37 -0000
@@ -202,10 +202,10 @@ update_action_sensitivity (EvWindow *ev_
 		page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
 		n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
 
-		set_action_sensitive (ev_window, "GoPreviousPage", page > 1);
-		set_action_sensitive (ev_window, "GoNextPage", page < n_pages);
-		set_action_sensitive (ev_window, "GoFirstPage", page > 1);
-		set_action_sensitive (ev_window, "GoLastPage", page < n_pages);
+		set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
+		set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
+		set_action_sensitive (ev_window, "GoFirstPage", page > 0);
+		set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
 	} else {
   		set_action_sensitive (ev_window, "GoFirstPage", FALSE);
 		set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
@@ -495,7 +495,8 @@ update_total_pages (EvWindow *ev_window)
 static gboolean
 document_supports_sidebar (EvDocument *document)
 {
-	return (EV_IS_DOCUMENT_THUMBNAILS (document) && EV_IS_DOCUMENT_LINKS (document));
+        /* FIXME: Remove the (TRUE ||) after links are fixed in poppler-glib */
+	return (EV_IS_DOCUMENT_THUMBNAILS (document) && (EV_IS_DOCUMENT_LINKS (document)));
 }
 
 static void


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