1 /* this file is part of evince, a gnome document viewer
3 * Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
5 * Evince is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * Evince is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <glib/gi18n-lib.h>
23 #include <libgxps/gxps.h>
25 #include "xps-document.h"
26 #include "ev-document-links.h"
27 #include "ev-document-print.h"
28 #include "ev-document-misc.h"
38 struct _XPSDocumentClass {
39 EvDocumentClass parent_class;
42 static void xps_document_document_links_iface_init (EvDocumentLinksInterface *iface);
43 static void xps_document_document_print_iface_init (EvDocumentPrintInterface *iface);
45 EV_BACKEND_REGISTER_WITH_CODE (XPSDocument, xps_document,
47 EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
48 xps_document_document_links_iface_init);
49 EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT,
50 xps_document_document_print_iface_init);
55 xps_document_init (XPSDocument *ps_document)
60 xps_document_dispose (GObject *object)
62 XPSDocument *xps = XPS_DOCUMENT (object);
65 g_object_unref (xps->file);
70 g_object_unref (xps->xps);
75 g_object_unref (xps->doc);
79 G_OBJECT_CLASS (xps_document_parent_class)->dispose (object);
84 xps_document_load (EvDocument *document,
88 XPSDocument *xps = XPS_DOCUMENT (document);
90 xps->file = g_file_new_for_uri (uri);
91 xps->xps = gxps_file_new (xps->file, error);
96 /* FIXME: what if there are multiple docs? */
97 xps->doc = gxps_file_get_document (xps->xps, 0, error);
99 g_object_unref (xps->xps);
109 xps_document_save (EvDocument *document,
113 XPSDocument *xps = XPS_DOCUMENT (document);
117 dest = g_file_new_for_uri (uri);
118 retval = g_file_copy (xps->file, dest,
119 G_FILE_COPY_TARGET_DEFAULT_PERMS |
120 G_FILE_COPY_OVERWRITE,
121 NULL, NULL, NULL, error);
122 g_object_unref (dest);
128 xps_document_get_n_pages (EvDocument *document)
130 XPSDocument *xps = XPS_DOCUMENT (document);
132 return gxps_document_get_n_pages (xps->doc);
136 xps_document_get_page (EvDocument *document,
139 XPSDocument *xps = XPS_DOCUMENT (document);
143 xps_page = gxps_document_get_page (xps->doc, index, NULL);
144 page = ev_page_new (index);
146 page->backend_page = (EvBackendPage)xps_page;
147 page->backend_destroy_func = (EvBackendPageDestroyFunc)g_object_unref;
154 xps_document_get_page_size (EvDocument *document,
162 xps_page = GXPS_PAGE (page->backend_page);
164 gxps_page_get_size (xps_page, &w, &h);
169 *height = (gdouble)h;
172 static EvDocumentInfo *
173 xps_document_get_info (EvDocument *document)
175 XPSDocument *xps = XPS_DOCUMENT (document);
176 EvDocumentInfo *info;
178 info = g_new0 (EvDocumentInfo, 1);
180 EV_DOCUMENT_INFO_N_PAGES |
181 EV_DOCUMENT_INFO_PAPER_SIZE;
184 if (gxps_document_get_n_pages (xps->doc) > 0) {
185 ev_document_get_page_size (document, 0,
186 &(info->paper_width),
187 &(info->paper_height));
188 info->paper_width = info->paper_width / 96.0f * 25.4f;
189 info->paper_height = info->paper_height / 96.0f * 25.4f;
192 info->n_pages = gxps_document_get_n_pages (xps->doc);
198 xps_document_get_backend_info (EvDocument *document,
199 EvDocumentBackendInfo *info)
201 info->name = "libgxps";
208 static cairo_surface_t *
209 xps_document_render (EvDocument *document,
213 guint page_width, page_height;
215 cairo_surface_t *surface;
217 GError *error = NULL;
219 xps_page = GXPS_PAGE (rc->page->backend_page);
221 gxps_page_get_size (xps_page, &page_width, &page_height);
222 if (rc->rotation == 90 || rc->rotation == 270) {
223 width = (guint) ((page_height * rc->scale) + 0.5);
224 height = (guint) ((page_width * rc->scale) + 0.5);
226 width = (guint) ((page_width * rc->scale) + 0.5);
227 height = (guint) ((page_height * rc->scale) + 0.5);
230 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
232 cr = cairo_create (surface);
234 cairo_set_source_rgb (cr, 1., 1., 1.);
237 switch (rc->rotation) {
239 cairo_translate (cr, width, 0);
242 cairo_translate (cr, width, height);
245 cairo_translate (cr, 0, height);
248 cairo_translate (cr, 0, 0);
251 cairo_scale (cr, rc->scale, rc->scale);
252 cairo_rotate (cr, rc->rotation * G_PI / 180.0);
253 gxps_page_render (xps_page, cr, &error);
257 g_warning ("Error rendering page %d: %s\n",
258 rc->page->index, error->message);
259 g_error_free (error);
266 xps_document_class_init (XPSDocumentClass *klass)
268 GObjectClass *object_class = G_OBJECT_CLASS (klass);
269 EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
271 object_class->dispose = xps_document_dispose;
273 ev_document_class->load = xps_document_load;
274 ev_document_class->save = xps_document_save;
275 ev_document_class->get_n_pages = xps_document_get_n_pages;
276 ev_document_class->get_page = xps_document_get_page;
277 ev_document_class->get_page_size = xps_document_get_page_size;
278 ev_document_class->get_info = xps_document_get_info;
279 ev_document_class->get_backend_info = xps_document_get_backend_info;
280 ev_document_class->render = xps_document_render;
283 /* EvDocumentLinks */
285 xps_document_links_has_document_links (EvDocumentLinks *document_links)
287 XPSDocument *xps_document = XPS_DOCUMENT (document_links);
288 GXPSDocumentStructure *structure;
291 structure = gxps_document_get_structure (xps_document->doc);
295 retval = gxps_document_structure_has_outline (structure);
296 g_object_unref (structure);
302 ev_link_from_target (XPSDocument *xps_document,
303 GXPSLinkTarget *target)
305 EvLinkAction *ev_action;
307 if (gxps_link_target_is_internal (target)) {
308 EvLinkDest *dest = NULL;
312 anchor = gxps_link_target_get_anchor (target);
314 /* FIXME: multidoc */
315 doc = gxps_file_get_document_for_link_target (xps_document->xps, target);
320 dest = ev_link_dest_new_named (anchor);
321 ev_action = ev_link_action_new_dest (dest);
322 } else if (doc == -1 && anchor &&
323 gxps_document_get_page_for_anchor (xps_document->doc, anchor) >= 0) {
324 /* Internal, but source is not a doc,
325 * let's try with doc = 0
327 dest = ev_link_dest_new_named (anchor);
328 ev_action = ev_link_action_new_dest (dest);
332 /* FIXME: remote uri? */
333 filename = g_file_get_path (xps_document->file);
336 dest = ev_link_dest_new_named (anchor);
337 ev_action = ev_link_action_new_remote (dest, filename);
343 uri = gxps_link_target_get_uri (target);
344 ev_action = ev_link_action_new_external_uri (uri);
347 return ev_link_new (NULL, ev_action);
351 build_tree (XPSDocument *xps_document,
354 GXPSOutlineIter *iter)
357 GtkTreeIter tree_iter;
358 GXPSOutlineIter child_iter;
360 GXPSLinkTarget *target;
363 target = gxps_outline_iter_get_target (iter);
364 title = g_markup_escape_text (gxps_outline_iter_get_description (iter), -1);
365 link = ev_link_from_target (xps_document, target);
366 gxps_link_target_free (target);
368 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
369 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
370 EV_DOCUMENT_LINKS_COLUMN_MARKUP, title,
371 EV_DOCUMENT_LINKS_COLUMN_LINK, link,
372 EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE,
374 g_object_unref (link);
377 if (gxps_outline_iter_children (&child_iter, iter))
378 build_tree (xps_document, model, &tree_iter, &child_iter);
379 } while (gxps_outline_iter_next (iter));
382 static GtkTreeModel *
383 xps_document_links_get_links_model (EvDocumentLinks *document_links)
385 XPSDocument *xps_document = XPS_DOCUMENT (document_links);
386 GXPSDocumentStructure *structure;
387 GXPSOutlineIter iter;
388 GtkTreeModel *model = NULL;
390 structure = gxps_document_get_structure (xps_document->doc);
394 if (gxps_document_structure_outline_iter_init (&iter, structure)) {
395 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
400 build_tree (xps_document, model, NULL, &iter);
403 g_object_unref (structure);
408 static EvMappingList *
409 xps_document_links_get_links (EvDocumentLinks *document_links,
412 XPSDocument *xps_document = XPS_DOCUMENT (document_links);
414 GList *retval = NULL;
418 xps_page = GXPS_PAGE (page->backend_page);
419 mapping_list = gxps_page_get_links (xps_page, NULL);
421 for (list = mapping_list; list; list = list->next) {
423 GXPSLinkTarget *target;
424 EvMapping *ev_link_mapping;
425 cairo_rectangle_t area;
427 xps_link = (GXPSLink *)list->data;
428 ev_link_mapping = g_new (EvMapping, 1);
429 gxps_link_get_area (xps_link, &area);
430 target = gxps_link_get_target (xps_link);
431 gxps_link_get_area (xps_link, &area);
432 ev_link_mapping->data = ev_link_from_target (xps_document, target);
434 ev_link_mapping->area.x1 = area.x;
435 ev_link_mapping->area.x2 = area.x + area.width;
436 ev_link_mapping->area.y1 = area.y;
437 ev_link_mapping->area.y2 = area.y + area.height;
439 retval = g_list_prepend (retval, ev_link_mapping);
440 gxps_link_free (xps_link);
443 g_list_free (mapping_list);
445 return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref);
449 xps_document_links_find_link_dest (EvDocumentLinks *document_links,
450 const gchar *link_name)
452 XPSDocument *xps_document = XPS_DOCUMENT (document_links);
455 cairo_rectangle_t area;
456 EvLinkDest *dest = NULL;
458 page = gxps_document_get_page_for_anchor (xps_document->doc, link_name);
462 xps_page = gxps_document_get_page (xps_document->doc, page, NULL);
466 if (gxps_page_get_anchor_destination (xps_page, link_name, &area, NULL))
467 dest = ev_link_dest_new_xyz (page, area.x, area.y, 1., TRUE, TRUE, FALSE);
469 g_object_unref (xps_page);
475 xps_document_links_find_link_page (EvDocumentLinks *document_links,
476 const gchar *link_name)
478 XPSDocument *xps_document = XPS_DOCUMENT (document_links);
480 return gxps_document_get_page_for_anchor (xps_document->doc, link_name);
484 xps_document_document_links_iface_init (EvDocumentLinksInterface *iface)
486 iface->has_document_links = xps_document_links_has_document_links;
487 iface->get_links_model = xps_document_links_get_links_model;
488 iface->get_links = xps_document_links_get_links;
489 iface->find_link_dest = xps_document_links_find_link_dest;
490 iface->find_link_page = xps_document_links_find_link_page;
493 /* EvDocumentPrint */
495 xps_document_print_print_page (EvDocumentPrint *document,
499 GError *error = NULL;
501 gxps_page_render (GXPS_PAGE (page->backend_page), cr, &error);
503 g_warning ("Error rendering page %d for printing: %s\n",
504 page->index, error->message);
505 g_error_free (error);
510 xps_document_document_print_iface_init (EvDocumentPrintInterface *iface)
512 iface->print_page = xps_document_print_print_page;