summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/Makefile.am4
-rw-r--r--backend/xps/Makefile.am31
-rw-r--r--backend/xps/xps-document.c505
-rw-r--r--backend/xps/xps-document.h45
-rw-r--r--backend/xps/xpsdocument.atril-backend.in5
-rw-r--r--configure.ac31
-rw-r--r--libdocument/ev-document-links.c14
-rw-r--r--libdocument/ev-document-links.h4
8 files changed, 638 insertions, 1 deletions
diff --git a/backend/Makefile.am b/backend/Makefile.am
index a6dc6e58..ab1663d7 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -30,6 +30,10 @@ if ENABLE_COMICS
SUBDIRS += comics
endif
+if ENABLE_XPS
+ SUBDIRS += xps
+endif
+
if ENABLE_IMPRESS
SUBDIRS += impress
endif
diff --git a/backend/xps/Makefile.am b/backend/xps/Makefile.am
new file mode 100644
index 00000000..2e0453bf
--- /dev/null
+++ b/backend/xps/Makefile.am
@@ -0,0 +1,31 @@
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libdocument \
+ -DMATELOCALEDIR=\"$(datadir)/locale\" \
+ -DATRIL_COMPILATION \
+ $(BACKEND_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+backend_LTLIBRARIES = libxpsdocument.la
+
+libxpsdocument_la_SOURCES = \
+ xps-document.c \
+ xps-document.h
+
+libxpsdocument_la_LDFLAGS = $(BACKEND_LIBTOOL_FLAGS)
+libxpsdocument_la_LIBADD = \
+ $(top_builddir)/libdocument/libatrildocument.la \
+ $(BACKEND_LIBS) \
+ $(GXPS_LIBS)
+
+backend_in_files = xpsdocument.atril-backend.in
+backend_DATA = $(backend_in_files:.atril-backend.in=.atril-backend)
+
+EXTRA_DIST = $(backend_in_files)
+
+CLEANFILES = $(backend_DATA)
+
+@EV_INTLTOOL_ATRIL_BACKEND_RULE@
+
+-include $(top_srcdir)/git.mk
diff --git a/backend/xps/xps-document.c b/backend/xps/xps-document.c
new file mode 100644
index 00000000..891f2008
--- /dev/null
+++ b/backend/xps/xps-document.c
@@ -0,0 +1,505 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * 2012 Leandro Vital <[email protected]>
+ *
+ * Atril 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.
+ *
+ * Atril 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n-lib.h>
+#include <libgxps/gxps.h>
+
+#include "xps-document.h"
+#include "ev-document-links.h"
+#include "ev-document-misc.h"
+#include "ev-document-print.h"
+
+struct _XPSDocument {
+ EvDocument object;
+
+ GFile *file;
+ GXPSFile *xps;
+ GXPSDocument *doc;
+};
+
+struct _XPSDocumentClass {
+ EvDocumentClass parent_class;
+};
+
+static void xps_document_document_links_iface_init (EvDocumentLinksInterface *iface);
+static void xps_document_document_print_iface_init (EvDocumentPrintInterface *iface);
+
+EV_BACKEND_REGISTER_WITH_CODE (XPSDocument, xps_document,
+ {
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
+ xps_document_document_links_iface_init);
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT,
+ xps_document_document_print_iface_init);
+ })
+
+/* XPSDocument */
+static void
+xps_document_init (XPSDocument *ps_document)
+{
+}
+
+static void
+xps_document_dispose (GObject *object)
+{
+ XPSDocument *xps = XPS_DOCUMENT (object);
+
+ if (xps->file) {
+ g_object_unref (xps->file);
+ xps->file = NULL;
+ }
+
+ if (xps->xps) {
+ g_object_unref (xps->xps);
+ xps->xps = NULL;
+ }
+
+ if (xps->doc) {
+ g_object_unref (xps->doc);
+ xps->doc = NULL;
+ }
+
+ G_OBJECT_CLASS (xps_document_parent_class)->dispose (object);
+}
+
+/* EvDocumentIface */
+static gboolean
+xps_document_load (EvDocument *document,
+ const char *uri,
+ GError **error)
+{
+ XPSDocument *xps = XPS_DOCUMENT (document);
+
+ xps->file = g_file_new_for_uri (uri);
+ xps->xps = gxps_file_new (xps->file, error);
+
+ if (!xps->xps)
+ return FALSE;
+
+ /* FIXME: what if there are multiple docs? */
+ xps->doc = gxps_file_get_document (xps->xps, 0, error);
+ if (!xps->doc) {
+ g_object_unref (xps->xps);
+ xps->xps = NULL;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+xps_document_save (EvDocument *document,
+ const char *uri,
+ GError **error)
+{
+ XPSDocument *xps = XPS_DOCUMENT (document);
+ GFile *dest;
+ gboolean retval;
+
+ dest = g_file_new_for_uri (uri);
+ retval = g_file_copy (xps->file, dest,
+ G_FILE_COPY_TARGET_DEFAULT_PERMS |
+ G_FILE_COPY_OVERWRITE,
+ NULL, NULL, NULL, error);
+ g_object_unref (dest);
+
+ return retval;
+}
+
+static gint
+xps_document_get_n_pages (EvDocument *document)
+{
+ XPSDocument *xps = XPS_DOCUMENT (document);
+
+ return gxps_document_get_n_pages (xps->doc);
+}
+
+static EvPage *
+xps_document_get_page (EvDocument *document,
+ gint index)
+{
+ XPSDocument *xps = XPS_DOCUMENT (document);
+ GXPSPage *xps_page;
+ EvPage *page;
+
+ xps_page = gxps_document_get_page (xps->doc, index, NULL);
+ page = ev_page_new (index);
+ if (xps_page) {
+ page->backend_page = (EvBackendPage)xps_page;
+ page->backend_destroy_func = (EvBackendPageDestroyFunc)g_object_unref;
+ }
+
+ return page;
+}
+
+static void
+xps_document_get_page_size (EvDocument *document,
+ EvPage *page,
+ double *width,
+ double *height)
+{
+ gxps_page_get_size (GXPS_PAGE (page->backend_page), width, height);
+}
+
+static EvDocumentInfo *
+xps_document_get_info (EvDocument *document)
+{
+ XPSDocument *xps = XPS_DOCUMENT (document);
+ EvDocumentInfo *info;
+
+ info = g_new0 (EvDocumentInfo, 1);
+ info->fields_mask =
+ EV_DOCUMENT_INFO_N_PAGES |
+ EV_DOCUMENT_INFO_PAPER_SIZE;
+
+
+ if (gxps_document_get_n_pages (xps->doc) > 0) {
+ ev_document_get_page_size (document, 0,
+ &(info->paper_width),
+ &(info->paper_height));
+ info->paper_width = info->paper_width / 96.0f * 25.4f;
+ info->paper_height = info->paper_height / 96.0f * 25.4f;
+ }
+
+ info->n_pages = gxps_document_get_n_pages (xps->doc);
+
+ return info;
+}
+
+static gboolean
+xps_document_get_backend_info (EvDocument *document,
+ EvDocumentBackendInfo *info)
+{
+ info->name = "libgxps";
+ /* FIXME */
+ info->version = "";
+
+ return TRUE;
+}
+
+static cairo_surface_t *
+xps_document_render (EvDocument *document,
+ EvRenderContext *rc)
+{
+ GXPSPage *xps_page;
+ gdouble page_width, page_height;
+ guint width, height;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ GError *error = NULL;
+
+ xps_page = GXPS_PAGE (rc->page->backend_page);
+
+ gxps_page_get_size (xps_page, &page_width, &page_height);
+ if (rc->rotation == 90 || rc->rotation == 270) {
+ width = (guint) ((page_height * rc->scale) + 0.5);
+ height = (guint) ((page_width * rc->scale) + 0.5);
+ } else {
+ width = (guint) ((page_width * rc->scale) + 0.5);
+ height = (guint) ((page_height * rc->scale) + 0.5);
+ }
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgb (cr, 1., 1., 1.);
+ cairo_paint (cr);
+
+ switch (rc->rotation) {
+ case 90:
+ cairo_translate (cr, width, 0);
+ break;
+ case 180:
+ cairo_translate (cr, width, height);
+ break;
+ case 270:
+ cairo_translate (cr, 0, height);
+ break;
+ default:
+ cairo_translate (cr, 0, 0);
+ }
+
+ cairo_scale (cr, rc->scale, rc->scale);
+ cairo_rotate (cr, rc->rotation * G_PI / 180.0);
+ gxps_page_render (xps_page, cr, &error);
+ cairo_destroy (cr);
+
+ if (error) {
+ g_warning ("Error rendering page %d: %s\n",
+ rc->page->index, error->message);
+ g_error_free (error);
+ }
+
+ return surface;
+}
+
+static void
+xps_document_class_init (XPSDocumentClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
+
+ object_class->dispose = xps_document_dispose;
+
+ ev_document_class->load = xps_document_load;
+ ev_document_class->save = xps_document_save;
+ ev_document_class->get_n_pages = xps_document_get_n_pages;
+ ev_document_class->get_page = xps_document_get_page;
+ ev_document_class->get_page_size = xps_document_get_page_size;
+ ev_document_class->get_info = xps_document_get_info;
+ ev_document_class->get_backend_info = xps_document_get_backend_info;
+ ev_document_class->render = xps_document_render;
+}
+
+/* EvDocumentLinks */
+static gboolean
+xps_document_links_has_document_links (EvDocumentLinks *document_links)
+{
+ XPSDocument *xps_document = XPS_DOCUMENT (document_links);
+ GXPSDocumentStructure *structure;
+ gboolean retval;
+
+ structure = gxps_document_get_structure (xps_document->doc);
+ if (!structure)
+ return FALSE;
+
+ retval = gxps_document_structure_has_outline (structure);
+ g_object_unref (structure);
+
+ return retval;
+}
+
+static EvLink *
+ev_link_from_target (XPSDocument *xps_document,
+ GXPSLinkTarget *target)
+{
+ EvLinkAction *ev_action;
+
+ if (gxps_link_target_is_internal (target)) {
+ EvLinkDest *dest = NULL;
+ guint doc;
+ const gchar *anchor;
+
+ anchor = gxps_link_target_get_anchor (target);
+
+ /* FIXME: multidoc */
+ doc = gxps_file_get_document_for_link_target (xps_document->xps, target);
+ if (doc == 0) {
+ if (!anchor)
+ return NULL;
+
+ dest = ev_link_dest_new_named (anchor);
+ ev_action = ev_link_action_new_dest (dest);
+ } else if (doc == -1 && anchor &&
+ gxps_document_get_page_for_anchor (xps_document->doc, anchor) >= 0) {
+ /* Internal, but source is not a doc,
+ * let's try with doc = 0
+ */
+ dest = ev_link_dest_new_named (anchor);
+ ev_action = ev_link_action_new_dest (dest);
+ } else {
+ gchar *filename;
+
+ /* FIXME: remote uri? */
+ filename = g_file_get_path (xps_document->file);
+
+ if (anchor)
+ dest = ev_link_dest_new_named (anchor);
+ ev_action = ev_link_action_new_remote (dest, filename);
+ g_free (filename);
+ }
+ } else {
+ const gchar *uri;
+
+ uri = gxps_link_target_get_uri (target);
+ ev_action = ev_link_action_new_external_uri (uri);
+ }
+
+ return ev_link_new (NULL, ev_action);
+}
+
+static void
+build_tree (XPSDocument *xps_document,
+ GtkTreeModel *model,
+ GtkTreeIter *parent,
+ GXPSOutlineIter *iter)
+{
+ do {
+ GtkTreeIter tree_iter;
+ GXPSOutlineIter child_iter;
+ EvLink *link;
+ GXPSLinkTarget *target;
+ gchar *title;
+
+ target = gxps_outline_iter_get_target (iter);
+ title = g_markup_escape_text (gxps_outline_iter_get_description (iter), -1);
+ link = ev_link_from_target (xps_document, target);
+ gxps_link_target_free (target);
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, title,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, link,
+ EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE,
+ -1);
+ g_object_unref (link);
+ g_free (title);
+
+ if (gxps_outline_iter_children (&child_iter, iter))
+ build_tree (xps_document, model, &tree_iter, &child_iter);
+ } while (gxps_outline_iter_next (iter));
+}
+
+static GtkTreeModel *
+xps_document_links_get_links_model (EvDocumentLinks *document_links)
+{
+ XPSDocument *xps_document = XPS_DOCUMENT (document_links);
+ GXPSDocumentStructure *structure;
+ GXPSOutlineIter iter;
+ GtkTreeModel *model = NULL;
+
+ structure = gxps_document_get_structure (xps_document->doc);
+ if (!structure)
+ return NULL;
+
+ if (gxps_document_structure_outline_iter_init (&iter, structure)) {
+ model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_OBJECT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING);
+ build_tree (xps_document, model, NULL, &iter);
+ }
+
+ g_object_unref (structure);
+
+ return model;
+}
+
+static EvMappingList *
+xps_document_links_get_links (EvDocumentLinks *document_links,
+ EvPage *page)
+{
+ XPSDocument *xps_document = XPS_DOCUMENT (document_links);
+ GXPSPage *xps_page;
+ GList *retval = NULL;
+ GList *mapping_list;
+ GList *list;
+
+ xps_page = GXPS_PAGE (page->backend_page);
+ mapping_list = gxps_page_get_links (xps_page, NULL);
+
+ for (list = mapping_list; list; list = list->next) {
+ GXPSLink *xps_link;
+ GXPSLinkTarget *target;
+ EvMapping *ev_link_mapping;
+ cairo_rectangle_t area;
+
+ xps_link = (GXPSLink *)list->data;
+ ev_link_mapping = g_new (EvMapping, 1);
+ gxps_link_get_area (xps_link, &area);
+ target = gxps_link_get_target (xps_link);
+ gxps_link_get_area (xps_link, &area);
+ ev_link_mapping->data = ev_link_from_target (xps_document, target);
+
+ ev_link_mapping->area.x1 = area.x;
+ ev_link_mapping->area.x2 = area.x + area.width;
+ ev_link_mapping->area.y1 = area.y;
+ ev_link_mapping->area.y2 = area.y + area.height;
+
+ retval = g_list_prepend (retval, ev_link_mapping);
+ gxps_link_free (xps_link);
+ }
+
+ g_list_free (mapping_list);
+
+ return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref);
+}
+
+static EvLinkDest *
+xps_document_links_find_link_dest (EvDocumentLinks *document_links, const gchar *link_name)
+{
+ XPSDocument *xps_document = XPS_DOCUMENT (document_links);
+ GXPSPage *xps_page;
+ gint page;
+ cairo_rectangle_t area;
+ EvLinkDest *dest = NULL;
+
+ page = gxps_document_get_page_for_anchor (xps_document->doc, link_name);
+ if (page == -1)
+ return NULL;
+
+ xps_page = gxps_document_get_page (xps_document->doc, page, NULL);
+ if (!xps_page)
+ return NULL;
+
+ if (gxps_page_get_anchor_destination (xps_page, link_name, &area, NULL))
+ dest = ev_link_dest_new_xyz (page, area.x, area.y, 1., TRUE, TRUE, FALSE);
+
+ g_object_unref (xps_page);
+
+ return dest;
+}
+
+static gint
+xps_document_links_find_link_page (EvDocumentLinks *document_links,
+ const gchar *link_name)
+{
+ XPSDocument *xps_document = XPS_DOCUMENT (document_links);
+
+ return gxps_document_get_page_for_anchor (xps_document->doc, link_name);
+}
+
+static void
+xps_document_document_links_iface_init (EvDocumentLinksInterface *iface)
+{
+ iface->has_document_links = xps_document_links_has_document_links;
+ iface->get_links_model = xps_document_links_get_links_model;
+ iface->get_links = xps_document_links_get_links;
+ iface->find_link_dest = xps_document_links_find_link_dest;
+ iface->find_link_page = xps_document_links_find_link_page;
+}
+
+
+/* EvDocumentPrint */
+static void
+xps_document_print_print_page (EvDocumentPrint *document,
+ EvPage *page,
+ cairo_t *cr)
+{
+ GError *error = NULL;
+
+ gxps_page_render (GXPS_PAGE (page->backend_page), cr, &error);
+ if (error) {
+ g_warning ("Error rendering page %d for printing: %s\n",
+ page->index, error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+xps_document_document_print_iface_init (EvDocumentPrintInterface *iface)
+{
+ iface->print_page = xps_document_print_print_page;
+}
+
diff --git a/backend/xps/xps-document.h b/backend/xps/xps-document.h
new file mode 100644
index 00000000..c5cc0cd6
--- /dev/null
+++ b/backend/xps/xps-document.h
@@ -0,0 +1,45 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * 2012 Leandro Vital <[email protected]>
+ *
+ * Atril 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.
+ *
+ * Atril 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __XPS_DOCUMENT_H__
+#define __XPS_DOCUMENT_H__
+
+#include <glib-object.h>
+
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+#define XPS_TYPE_DOCUMENT (xps_document_get_type())
+#define XPS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XPS_TYPE_DOCUMENT, XPSDocument))
+#define XPS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XPS_TYPE_DOCUMENT, XPSDocumentClass))
+#define XPS_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XPS_TYPE_DOCUMENT))
+#define XPS_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XPS_TYPE_DOCUMENT, XPSDocumentClass))
+
+typedef struct _XPSDocument XPSDocument;
+typedef struct _XPSDocumentClass XPSDocumentClass;
+
+GType xps_document_get_type (void) G_GNUC_CONST;
+
+G_MODULE_EXPORT GType register_evince_backend (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __XPS_DOCUMENT_H__ */
diff --git a/backend/xps/xpsdocument.atril-backend.in b/backend/xps/xpsdocument.atril-backend.in
new file mode 100644
index 00000000..3fca5801
--- /dev/null
+++ b/backend/xps/xpsdocument.atril-backend.in
@@ -0,0 +1,5 @@
+[Atril Backend]
+Module=xpsdocument
+Resident=true
+_TypeDescription=XPS Documents
+MimeType=application/oxps;application/vnd.ms-xpsdocument
diff --git a/configure.ac b/configure.ac
index ab808986..112e7264 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
# *****************************************************************************
m4_define([ev_major_version], [1])
-m4_define([ev_minor_version], [4])
+m4_define([ev_minor_version], [5])
m4_define([ev_micro_version], [0])
m4_define([ev_extra_version], [])
m4_define([ev_version], [ev_major_version.ev_minor_version.ev_micro_version()ev_extra_version])
@@ -679,6 +679,30 @@ AM_CONDITIONAL(ENABLE_COMICS, test x$enable_comics = xyes)
dnl ================== End of comic book checks ============================================
+dnl ================== XPS checks ===================================================
+
+AC_ARG_ENABLE(xps,
+ [AS_HELP_STRING([--enable-xps],
+ [Compile with support for XPS documents.])],
+ [enable_xps=$enableval],
+ [enable_xps=yes])
+
+if test "x$enable_xps" = "xyes"; then
+ GXPS_REQUIRED=0.0.1
+ PKG_CHECK_MODULES(GXPS, libgxps >= $GXPS_REQUIRED,enable_xps=yes,enable_xps=no)
+
+ if test "x$enable_xps" = "xyes"; then
+ AC_DEFINE([ENABLE_XPS], [1], [Enable support for XPS documents.])
+ else
+ enable_xps="no"
+ AC_MSG_WARN(["XPS support is disabled since libgxps (version >= $GXPS_REQUIRED) is needed"])
+ fi
+fi
+
+AM_CONDITIONAL(ENABLE_XPS, test x$enable_xps = xyes)
+
+dnl ================== End of XPS checks ===================================================
+
dnl ================== impress book checks ===================================================
AC_ARG_ENABLE(impress,
@@ -717,6 +741,9 @@ fi
if test "x$enable_pixbuf" = "xyes"; then
ATRIL_MIME_TYPES="${ATRIL_MIME_TYPES}image/*;"
fi
+if test "x$enable_xps" = "xyes"; then
+ EVINCE_MIME_TYPES="${EVINCE_MIME_TYPES}application/oxps;application/vnd.ms-xpsdocument;"
+fi
if test "x$enable_impress" = "xyes"; then
ATRIL_MIME_TYPES="${ATRIL_MIME_TYPES}application/vnd.sun.xml.impress;application/vnd.oasis.opendocument.presentation;"
fi
@@ -799,6 +826,7 @@ backend/pdf/Makefile
backend/pixbuf/Makefile
backend/ps/Makefile
backend/tiff/Makefile
+backend/xps/Makefile
cut-n-paste/Makefile
cut-n-paste/gimpcellrenderertoggle/Makefile
cut-n-paste/smclient/Makefile
@@ -883,5 +911,6 @@ Configure summary:
DVI Backend........: $enable_dvi
Pixbuf Backend.....: $enable_pixbuf
Comics Backend.....: $enable_comics
+ XPS Backend........: $enable_xps
Impress Backend....: $enable_impress
"
diff --git a/libdocument/ev-document-links.c b/libdocument/ev-document-links.c
index 3fa0b18b..1c8eb03e 100644
--- a/libdocument/ev-document-links.c
+++ b/libdocument/ev-document-links.c
@@ -77,6 +77,20 @@ ev_document_links_find_link_dest (EvDocumentLinks *document_links,
return retval;
}
+gint
+ev_document_links_find_link_page (EvDocumentLinks *document_links,
+ const gchar *link_name)
+{
+ EvDocumentLinksInterface *iface = EV_DOCUMENT_LINKS_GET_IFACE (document_links);
+ gint retval;
+
+ ev_document_doc_mutex_lock ();
+ retval = iface->find_link_page (document_links, link_name);
+ ev_document_doc_mutex_unlock ();
+
+ return retval;
+}
+
/* Helper functions */
gint
ev_document_links_get_dest_page (EvDocumentLinks *document_links,
diff --git a/libdocument/ev-document-links.h b/libdocument/ev-document-links.h
index 286131d4..75cba6a1 100644
--- a/libdocument/ev-document-links.h
+++ b/libdocument/ev-document-links.h
@@ -67,6 +67,8 @@ struct _EvDocumentLinksInterface
EvPage *page);
EvLinkDest *(* find_link_dest) (EvDocumentLinks *document_links,
const gchar *link_name);
+ gint (* find_link_page) (EvDocumentLinks *document_links,
+ const gchar *link_name);
};
GType ev_document_links_get_type (void) G_GNUC_CONST;
@@ -77,6 +79,8 @@ EvMappingList *ev_document_links_get_links (EvDocumentLinks *document_
EvPage *page);
EvLinkDest *ev_document_links_find_link_dest (EvDocumentLinks *document_links,
const gchar *link_name);
+gint ev_document_links_find_link_page (EvDocumentLinks *document_links,
+ const gchar *link_name);
gint ev_document_links_get_dest_page (EvDocumentLinks *document_links,
EvLinkDest *dest);
gchar *ev_document_links_get_dest_page_label (EvDocumentLinks *document_links,