]> www.fi.muni.cz Git - evince.git/blob - backend/pdf/ev-poppler.cc
8659d082db5803e15de872accd155f470ae75c3c
[evince.git] / backend / pdf / ev-poppler.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2009, Juanjo MarĂ­n <juanj.marin@juntadeandalucia.es>
5  * Copyright (C) 2004, Red Hat, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23
24 #include <math.h>
25 #include <string.h>
26 #include <gtk/gtk.h>
27 #include <poppler.h>
28 #include <poppler-document.h>
29 #include <poppler-page.h>
30 #ifdef HAVE_CAIRO_PDF
31 #include <cairo-pdf.h>
32 #endif
33 #ifdef HAVE_CAIRO_PS
34 #include <cairo-ps.h>
35 #endif
36 #include <glib/gi18n-lib.h>
37
38 #include "ev-poppler.h"
39 #include "ev-file-exporter.h"
40 #include "ev-mapping.h"
41 #include "ev-document-find.h"
42 #include "ev-document-misc.h"
43 #include "ev-document-links.h"
44 #include "ev-document-images.h"
45 #include "ev-document-fonts.h"
46 #include "ev-document-security.h"
47 #include "ev-document-thumbnails.h"
48 #include "ev-document-transition.h"
49 #include "ev-document-forms.h"
50 #include "ev-document-layers.h"
51 #include "ev-document-print.h"
52 #include "ev-document-annotations.h"
53 #include "ev-document-attachments.h"
54 #include "ev-selection.h"
55 #include "ev-transition-effect.h"
56 #include "ev-attachment.h"
57 #include "ev-image.h"
58
59 #include <libxml/tree.h>
60 #include <libxml/parser.h>
61 #include <libxml/xpath.h>
62 #include <libxml/xpathInternals.h>
63
64 #if (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS))
65 #define HAVE_CAIRO_PRINT
66 #endif
67
68 /* fields from the XMP Rights Management Schema, XMP Specification Sept 2005, pag. 45 */
69 #define LICENSE_MARKED "/x:xmpmeta/rdf:RDF/rdf:Description/xmpRights:Marked"
70 #define LICENSE_TEXT "/x:xmpmeta/rdf:RDF/rdf:Description/dc:rights/rdf:Alt/rdf:li[lang('%s')]"
71 #define LICENSE_WEB_STATEMENT "/x:xmpmeta/rdf:RDF/rdf:Description/xmpRights:WebStatement"
72 /* license field from Creative Commons schema, http://creativecommons.org/ns */
73 #define LICENSE_URI "/x:xmpmeta/rdf:RDF/rdf:Description/cc:license/@rdf:resource"
74
75 typedef struct {
76         EvFileExporterFormat format;
77
78         /* Pages per sheet */
79         gint pages_per_sheet;
80         gint pages_printed;
81         gint pages_x;
82         gint pages_y;
83         gdouble paper_width;
84         gdouble paper_height;
85         
86 #ifdef HAVE_CAIRO_PRINT
87         cairo_t *cr;
88 #else
89         PopplerPSFile *ps_file;
90 #endif
91 } PdfPrintContext;
92
93 struct _PdfDocumentClass
94 {
95         EvDocumentClass parent_class;
96 };
97
98 struct _PdfDocument
99 {
100         EvDocument parent_instance;
101
102         PopplerDocument *document;
103         gchar *password;
104         gboolean modified;
105
106         PopplerFontInfo *font_info;
107         PopplerFontsIter *fonts_iter;
108         int fonts_scanned_pages;
109
110         PdfPrintContext *print_ctx;
111
112         GList *layers;
113 };
114
115 static void pdf_document_security_iface_init             (EvDocumentSecurityInterface    *iface);
116 static void pdf_document_document_thumbnails_iface_init  (EvDocumentThumbnailsInterface  *iface);
117 static void pdf_document_document_links_iface_init       (EvDocumentLinksInterface       *iface);
118 static void pdf_document_document_images_iface_init      (EvDocumentImagesInterface      *iface);
119 static void pdf_document_document_forms_iface_init       (EvDocumentFormsInterface       *iface);
120 static void pdf_document_document_fonts_iface_init       (EvDocumentFontsInterface       *iface);
121 static void pdf_document_document_layers_iface_init      (EvDocumentLayersInterface      *iface);
122 static void pdf_document_document_print_iface_init       (EvDocumentPrintInterface       *iface);
123 static void pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface);
124 static void pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface);
125 static void pdf_document_find_iface_init                 (EvDocumentFindInterface        *iface);
126 static void pdf_document_file_exporter_iface_init        (EvFileExporterInterface        *iface);
127 static void pdf_selection_iface_init                     (EvSelectionInterface           *iface);
128 static void pdf_document_page_transition_iface_init      (EvDocumentTransitionInterface  *iface);
129 static void pdf_document_thumbnails_get_dimensions       (EvDocumentThumbnails           *document_thumbnails,
130                                                           EvRenderContext                *rc,
131                                                           gint                           *width,
132                                                           gint                           *height);
133 static int  pdf_document_get_n_pages                     (EvDocument                     *document);
134
135 static EvLinkDest *ev_link_dest_from_dest    (PdfDocument       *pdf_document,
136                                               PopplerDest       *dest);
137 static EvLink     *ev_link_from_action       (PdfDocument       *pdf_document,
138                                               PopplerAction     *action);
139 static void        pdf_print_context_free    (PdfPrintContext   *ctx);
140 static gboolean    attachment_save_to_buffer (PopplerAttachment *attachment,
141                                               gchar            **buffer,
142                                               gsize             *buffer_size,
143                                               GError           **error);
144
145 EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document,
146                          {
147                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
148                                                                  pdf_document_security_iface_init);
149                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
150                                                                  pdf_document_document_thumbnails_iface_init);
151                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
152                                                                  pdf_document_document_links_iface_init);
153                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
154                                                                  pdf_document_document_images_iface_init);
155                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
156                                                                  pdf_document_document_forms_iface_init);
157                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
158                                                                  pdf_document_document_fonts_iface_init);
159                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LAYERS,
160                                                                  pdf_document_document_layers_iface_init);
161                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT,
162                                                                  pdf_document_document_print_iface_init);
163                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_ANNOTATIONS,
164                                                                  pdf_document_document_annotations_iface_init);
165                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_ATTACHMENTS,
166                                                                  pdf_document_document_attachments_iface_init);
167                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
168                                                                  pdf_document_find_iface_init);
169                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
170                                                                  pdf_document_file_exporter_iface_init);
171                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
172                                                                  pdf_selection_iface_init);
173                                  EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
174                                                                  pdf_document_page_transition_iface_init);
175                          });
176
177 static void
178 pdf_document_dispose (GObject *object)
179 {
180         PdfDocument *pdf_document = PDF_DOCUMENT(object);
181
182         if (pdf_document->print_ctx) {
183                 pdf_print_context_free (pdf_document->print_ctx);
184                 pdf_document->print_ctx = NULL;
185         }
186
187         if (pdf_document->document) {
188                 g_object_unref (pdf_document->document);
189         }
190
191         if (pdf_document->font_info) { 
192                 poppler_font_info_free (pdf_document->font_info);
193         }
194
195         if (pdf_document->fonts_iter) {
196                 poppler_fonts_iter_free (pdf_document->fonts_iter);
197         }
198
199         if (pdf_document->layers) {
200                 g_list_foreach (pdf_document->layers, (GFunc)g_object_unref, NULL);
201                 g_list_free (pdf_document->layers);
202         }
203
204         G_OBJECT_CLASS (pdf_document_parent_class)->dispose (object);
205 }
206
207 static void
208 pdf_document_init (PdfDocument *pdf_document)
209 {
210         pdf_document->password = NULL;
211 }
212
213 static void
214 convert_error (GError  *poppler_error,
215                GError **error)
216 {
217         if (poppler_error == NULL)
218                 return;
219
220         if (poppler_error->domain == POPPLER_ERROR) {
221                 /* convert poppler errors into EvDocument errors */
222                 gint code = EV_DOCUMENT_ERROR_INVALID;
223                 if (poppler_error->code == POPPLER_ERROR_INVALID)
224                         code = EV_DOCUMENT_ERROR_INVALID;
225                 else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED)
226                         code = EV_DOCUMENT_ERROR_ENCRYPTED;
227                         
228                 g_set_error_literal (error,
229                                      EV_DOCUMENT_ERROR,
230                                      code,
231                                      poppler_error->message);
232
233                 g_error_free (poppler_error);
234         } else {
235                 g_propagate_error (error, poppler_error);
236         }
237 }
238
239
240 /* EvDocument */
241 static gboolean
242 pdf_document_save (EvDocument  *document,
243                    const char  *uri,
244                    GError     **error)
245 {
246         PdfDocument *pdf_document = PDF_DOCUMENT (document);
247         gboolean retval;
248         GError *poppler_error = NULL;
249
250         if (pdf_document->modified) {
251                 retval = poppler_document_save (pdf_document->document,
252                                                 uri, &poppler_error);
253         } else {
254                 retval = poppler_document_save_a_copy (pdf_document->document,
255                                                        uri, &poppler_error);
256         }
257                                                        
258         if (! retval)
259                 convert_error (poppler_error, error);
260
261         return retval;
262 }
263
264 static gboolean
265 pdf_document_load (EvDocument   *document,
266                    const char   *uri,
267                    GError      **error)
268 {
269         GError *poppler_error = NULL;
270         PdfDocument *pdf_document = PDF_DOCUMENT (document);
271
272         pdf_document->document =
273                 poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
274
275         if (pdf_document->document == NULL) {
276                 convert_error (poppler_error, error);
277                 return FALSE;
278         }
279
280         return TRUE;
281 }
282
283 static int
284 pdf_document_get_n_pages (EvDocument *document)
285 {
286         return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
287 }
288
289 static EvPage *
290 pdf_document_get_page (EvDocument *document,
291                        gint        index)
292 {
293         PdfDocument *pdf_document = PDF_DOCUMENT (document);
294         PopplerPage *poppler_page;
295         EvPage      *page;
296
297         poppler_page = poppler_document_get_page (pdf_document->document, index);
298         page = ev_page_new (index);
299         page->backend_page = (EvBackendPage)g_object_ref (poppler_page);
300         page->backend_destroy_func = (EvBackendPageDestroyFunc)g_object_unref;
301         g_object_unref (poppler_page);
302
303         return page;
304 }
305
306 static void
307 pdf_document_get_page_size (EvDocument *document,
308                             EvPage     *page,
309                             double     *width,
310                             double     *height)
311 {
312         g_return_if_fail (POPPLER_IS_PAGE (page->backend_page));
313         
314         poppler_page_get_size (POPPLER_PAGE (page->backend_page), width, height);
315 }
316
317 static char *
318 pdf_document_get_page_label (EvDocument *document,
319                              EvPage     *page)
320 {
321         char *label = NULL;
322
323         g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
324
325         g_object_get (G_OBJECT (page->backend_page),
326                       "label", &label,
327                       NULL);
328         return label;
329 }
330
331 static cairo_surface_t *
332 pdf_page_render (PopplerPage     *page,
333                  gint             width,
334                  gint             height,
335                  EvRenderContext *rc)
336 {
337         cairo_surface_t *surface;
338         cairo_t *cr;
339
340         surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
341                                               width, height);
342         cr = cairo_create (surface);
343
344         switch (rc->rotation) {
345                 case 90:
346                         cairo_translate (cr, width, 0);
347                         break;
348                 case 180:
349                         cairo_translate (cr, width, height);
350                         break;
351                 case 270:
352                         cairo_translate (cr, 0, height);
353                         break;
354                 default:
355                         cairo_translate (cr, 0, 0);
356         }
357         cairo_scale (cr, rc->scale, rc->scale);
358         cairo_rotate (cr, rc->rotation * G_PI / 180.0);
359         poppler_page_render (page, cr);
360
361         cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
362         cairo_set_source_rgb (cr, 1., 1., 1.);
363         cairo_paint (cr);
364
365         cairo_destroy (cr);
366
367         return surface;
368 }
369
370 static cairo_surface_t *
371 pdf_document_render (EvDocument      *document,
372                      EvRenderContext *rc)
373 {
374         PdfDocument *pdf_document;
375         PopplerPage *poppler_page;
376         double width_points, height_points;
377         gint width, height;
378
379         poppler_page = POPPLER_PAGE (rc->page->backend_page);
380
381         poppler_page_get_size (poppler_page,
382                                &width_points, &height_points);
383         
384         if (rc->rotation == 90 || rc->rotation == 270) {
385                 width = (int) ((height_points * rc->scale) + 0.5);
386                 height = (int) ((width_points * rc->scale) + 0.5);
387         } else {
388                 width = (int) ((width_points * rc->scale) + 0.5);
389                 height = (int) ((height_points * rc->scale) + 0.5);
390         }
391         
392         return pdf_page_render (poppler_page,
393                                 width, height, rc);
394 }
395
396 /* reference:
397 http://www.pdfa.org/lib/exe/fetch.php?id=pdfa%3Aen%3Atechdoc&cache=cache&media=pdfa:techdoc:tn0001_pdfa-1_and_namespaces_2008-03-18.pdf */
398 static char *
399 pdf_document_get_format_from_metadata (xmlDocPtr          doc,
400                                        xmlXPathContextPtr xpathCtx)
401 {
402         xmlXPathObjectPtr xpathObj;
403         xmlChar *part = NULL;
404         xmlChar *conf = NULL;
405         char *result = NULL;
406         int i;
407
408         /* add pdf/a namespaces */
409         xmlXPathRegisterNs (xpathCtx, BAD_CAST "x", BAD_CAST "adobe:ns:meta/");
410         xmlXPathRegisterNs (xpathCtx, BAD_CAST "rdf", BAD_CAST "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
411         xmlXPathRegisterNs (xpathCtx, BAD_CAST "pdfaid", BAD_CAST "http://www.aiim.org/pdfa/ns/id/");
412
413         /* reads pdf/a part */
414         /* first syntax: child node */
415         xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/pdfaid:part", xpathCtx);
416         if (xpathObj != NULL) {
417                 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0)
418                         part = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
419
420                 xmlXPathFreeObject (xpathObj);
421         }
422         if (part == NULL) {
423                 /* second syntax: attribute */
424                 xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/@pdfaid:part", xpathCtx);
425                 if (xpathObj != NULL) {
426                         if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0)
427                                 part = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
428
429                         xmlXPathFreeObject (xpathObj);
430                 }
431         }
432
433         /* reads pdf/a conformance */
434         /* first syntax: child node */
435         xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/pdfaid:conformance", xpathCtx);
436         if (xpathObj != NULL) {
437                 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0)
438                         conf = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
439
440                 xmlXPathFreeObject (xpathObj);
441         }
442         if (conf == NULL) {
443                 /* second syntax: attribute */
444                 xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/@pdfaid:conformance", xpathCtx);
445                 if (xpathObj != NULL) {
446                         if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0)
447                                 conf = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
448
449                         xmlXPathFreeObject (xpathObj);
450                 }
451         }
452
453         if (part != NULL && conf != NULL) {
454                 /* makes conf lowercase */
455                 for (i = 0; conf[i]; i++)
456                         conf[i] = g_ascii_tolower (conf[i]);
457
458                 /* return buffer */
459                 result = g_strdup_printf ("PDF/A - %s%s", part, conf);
460         }
461
462         /* Cleanup */
463         xmlFree (part);
464         xmlFree (conf);
465
466         return result;
467 }
468
469 static EvDocumentLicense *
470 pdf_document_get_license_from_metadata (xmlDocPtr          doc,
471                                         xmlXPathContextPtr xpathCtx)
472 {
473         xmlXPathObjectPtr xpathObj;
474         xmlChar *marked = NULL;
475         const char *language_string;
476         char  *aux;
477         gchar **tags;
478         gchar *tag, *tag_aux;
479         int i, j;
480         EvDocumentLicense *license;
481
482         /* register namespaces */
483         xmlXPathRegisterNs (xpathCtx, BAD_CAST "x", BAD_CAST "adobe:ns:meta/");
484         xmlXPathRegisterNs (xpathCtx, BAD_CAST "rdf", BAD_CAST "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
485         xmlXPathRegisterNs (xpathCtx, BAD_CAST "dc", BAD_CAST "http://purl.org/dc/elements/1.1/");
486         /* XMP Rights Management Schema */
487         xmlXPathRegisterNs (xpathCtx, BAD_CAST "xmpRights", BAD_CAST "http://ns.adobe.com/xap/1.0/rights/");
488         /* Creative Commons Schema */
489         xmlXPathRegisterNs (xpathCtx, BAD_CAST "cc", BAD_CAST "http://creativecommons.org/ns#");
490
491         /* checking if the document has been marked as defined on the XMP Rights
492          * Management Schema */
493         xpathObj = xmlXPathEvalExpression (BAD_CAST LICENSE_MARKED, xpathCtx);
494         if (xpathObj != NULL) {
495                 if (xpathObj->nodesetval != NULL &&
496                     xpathObj->nodesetval->nodeNr != 0)
497                         marked = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
498                 xmlXPathFreeObject (xpathObj);
499         }
500
501         /* a) Not marked => No XMP Rights information */
502         if (!marked) {
503                 xmlFree (marked);
504                 return NULL;
505         }
506
507         license = ev_document_license_new ();
508
509         /* b) Marked False => Public Domain, no copyrighted material and no
510          * license needed */
511         if (g_strrstr ((char *) marked, "False") != NULL) {
512                 license->text = g_strdup (_("This work is in the Public Domain"));
513         /* c) Marked True => Copyrighted material */
514         } else {
515                 /* Checking usage terms as defined by the XMP Rights Management
516                  * Schema. This field is recomended to be checked by Creative
517                  * Commons */
518                 /* 1) checking for a suitable localized string */
519                 language_string = pango_language_to_string (gtk_get_default_language ());
520                 tags = g_strsplit (language_string, "-", -1);
521                 i = g_strv_length (tags);
522                 while (i-- && !license->text) {
523                         tag = g_strdup (tags[0]);
524                         for (j = 1; j <= i; j++) {
525                                 tag_aux = g_strdup_printf ("%s-%s", tag, tags[j]);
526                                 g_free (tag);
527                                 tag = tag_aux;
528                         }
529                         aux = g_strdup_printf (LICENSE_TEXT, tag);
530                         xpathObj = xmlXPathEvalExpression (BAD_CAST aux, xpathCtx);
531                         if (xpathObj != NULL) {
532                                 if (xpathObj->nodesetval != NULL &&
533                                     xpathObj->nodesetval->nodeNr != 0)
534                                         license->text = (gchar *)xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
535                                 xmlXPathFreeObject (xpathObj);
536                         }
537                         g_free (tag);
538                         g_free (aux);
539                 }
540                 g_strfreev(tags);
541
542                 /* 2) if not, use the default string */
543                 if (!license->text) {
544                         aux = g_strdup_printf (LICENSE_TEXT, "x-default");
545                         xpathObj = xmlXPathEvalExpression (BAD_CAST aux, xpathCtx);
546                         if (xpathObj != NULL) {
547                                 if (xpathObj->nodesetval != NULL &&
548                                     xpathObj->nodesetval->nodeNr != 0)
549                                         license->text = (gchar *)xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
550                                 xmlXPathFreeObject (xpathObj);
551                         }
552                         g_free (aux);
553                 }
554
555                 /* Checking the license URI as defined by the Creative Commons
556                  * Schema. This field is recomended to be checked by Creative
557                  * Commons */
558                 xpathObj = xmlXPathEvalExpression (BAD_CAST LICENSE_URI, xpathCtx);
559                 if (xpathObj != NULL) {
560                         if (xpathObj->nodesetval != NULL &&
561                             xpathObj->nodesetval->nodeNr != 0)
562                                 license->uri = (gchar *)xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
563                         xmlXPathFreeObject (xpathObj);
564                 }
565
566                 /* Checking the web statement as defined by the XMP Rights
567                  * Management Schema. Checking it out is a sort of above-and-beyond
568                  * the basic recommendations by Creative Commons. It can be
569                  * considered as a "reinforcement" approach to add certainty. */
570                 xpathObj = xmlXPathEvalExpression (BAD_CAST LICENSE_WEB_STATEMENT, xpathCtx);
571                 if (xpathObj != NULL) {
572                         if (xpathObj->nodesetval != NULL &&
573                             xpathObj->nodesetval->nodeNr != 0)
574                                 license->web_statement = (gchar *)xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]);
575                         xmlXPathFreeObject (xpathObj);
576                 }
577         }
578         xmlFree (marked);
579
580         if (!license->text && !license->uri && !license->web_statement) {
581                 ev_document_license_free (license);
582                 return NULL;
583         }
584
585         return license;
586 }
587
588 static void
589 pdf_document_parse_metadata (const gchar    *metadata,
590                              EvDocumentInfo *info)
591 {
592         xmlDocPtr          doc;
593         xmlXPathContextPtr xpathCtx;
594         gchar             *fmt;
595
596         doc = xmlParseMemory (metadata, strlen (metadata));
597         if (doc == NULL)
598                 return;         /* invalid xml metadata */
599
600         xpathCtx = xmlXPathNewContext (doc);
601         if (xpathCtx == NULL) {
602                 xmlFreeDoc (doc);
603                 return;         /* invalid xpath context */
604         }
605
606         fmt = pdf_document_get_format_from_metadata (doc, xpathCtx);
607         if (fmt != NULL) {
608                 g_free (info->format);
609                 info->format = fmt;
610         }
611
612         info->license = pdf_document_get_license_from_metadata (doc, xpathCtx);
613
614         xmlXPathFreeContext (xpathCtx);
615         xmlFreeDoc (doc);
616 }
617
618
619 static EvDocumentInfo *
620 pdf_document_get_info (EvDocument *document)
621 {
622         EvDocumentInfo *info;
623         PopplerPageLayout layout;
624         PopplerPageMode mode;
625         PopplerViewerPreferences view_prefs;
626         PopplerPermissions permissions;
627         EvPage *page;
628         char *metadata;
629
630         info = g_new0 (EvDocumentInfo, 1);
631
632         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
633                             EV_DOCUMENT_INFO_FORMAT |
634                             EV_DOCUMENT_INFO_AUTHOR |
635                             EV_DOCUMENT_INFO_SUBJECT |
636                             EV_DOCUMENT_INFO_KEYWORDS |
637                             EV_DOCUMENT_INFO_LAYOUT |
638                             EV_DOCUMENT_INFO_START_MODE |
639                             EV_DOCUMENT_INFO_PERMISSIONS |
640                             EV_DOCUMENT_INFO_UI_HINTS |
641                             EV_DOCUMENT_INFO_CREATOR |
642                             EV_DOCUMENT_INFO_PRODUCER |
643                             EV_DOCUMENT_INFO_CREATION_DATE |
644                             EV_DOCUMENT_INFO_MOD_DATE |
645                             EV_DOCUMENT_INFO_LINEARIZED |
646                             EV_DOCUMENT_INFO_N_PAGES |
647                             EV_DOCUMENT_INFO_SECURITY | 
648                             EV_DOCUMENT_INFO_PAPER_SIZE |
649                             EV_DOCUMENT_INFO_LICENSE;
650
651         g_object_get (PDF_DOCUMENT (document)->document,
652                       "title", &(info->title),
653                       "format", &(info->format),
654                       "author", &(info->author),
655                       "subject", &(info->subject),
656                       "keywords", &(info->keywords),
657                       "page-mode", &mode,
658                       "page-layout", &layout,
659                       "viewer-preferences", &view_prefs,
660                       "permissions", &permissions,
661                       "creator", &(info->creator),
662                       "producer", &(info->producer),
663                       "creation-date", &(info->creation_date),
664                       "mod-date", &(info->modified_date),
665                       "linearized", &(info->linearized),
666                       "metadata", &metadata,
667                       NULL);
668
669         if (metadata != NULL) {
670                 pdf_document_parse_metadata (metadata, info);
671                 g_free (metadata);
672         }
673
674         info->n_pages = ev_document_get_n_pages (document);
675
676         if (info->n_pages > 0) {
677                 ev_document_get_page_size (document, 0,
678                                            &(info->paper_width),
679                                            &(info->paper_height));
680                 // Convert to mm.
681                 info->paper_width = info->paper_width / 72.0f * 25.4f;
682                 info->paper_height = info->paper_height / 72.0f * 25.4f;
683         }
684
685         switch (layout) {
686                 case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
687                         info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
688                         break;
689                 case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
690                         info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
691                         break;
692                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
693                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
694                         break;
695                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
696                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
697                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
698                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
699                         break;
700                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
701                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
702                         break;
703                 default:
704                         break;
705         }
706
707         switch (mode) {
708                 case POPPLER_PAGE_MODE_NONE:
709                         info->mode = EV_DOCUMENT_MODE_NONE;
710                         break;
711                 case POPPLER_PAGE_MODE_USE_THUMBS:
712                         info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
713                         break;
714                 case POPPLER_PAGE_MODE_USE_OC:
715                         info->mode = EV_DOCUMENT_MODE_USE_OC;
716                         break;
717                 case POPPLER_PAGE_MODE_FULL_SCREEN:
718                         info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
719                         break;
720                 case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
721                         info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
722                 default:
723                         break;
724         }
725
726         info->ui_hints = 0;
727         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
728                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
729         }
730         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
731                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
732         }
733         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
734                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
735         }
736         if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
737                 info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
738         }
739         if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
740                 info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
741         }
742         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
743                 info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
744         }
745         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
746                 info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
747         }
748
749         info->permissions = 0;
750         if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
751                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
752         }
753         if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
754                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
755         }
756         if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
757                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
758         }
759         if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
760                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
761         }
762
763         if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) {
764                 /* translators: this is the document security state */
765                 info->security = g_strdup (_("Yes"));
766         } else {
767                 /* translators: this is the document security state */
768                 info->security = g_strdup (_("No"));
769         }
770
771         return info;
772 }
773
774 static gboolean
775 pdf_document_get_backend_info (EvDocument *document, EvDocumentBackendInfo *info)
776 {
777         PopplerBackend backend;
778
779         backend = poppler_get_backend ();
780         switch (backend) {
781                 case POPPLER_BACKEND_CAIRO:
782                         info->name = "poppler/cairo";
783                         break;
784                 case POPPLER_BACKEND_SPLASH:
785                         info->name = "poppler/splash";
786                         break;
787                 default:
788                         info->name = "poppler/unknown";
789                         break;
790         }
791
792         info->version = poppler_get_version ();
793
794         return TRUE;
795 }
796
797 static void
798 pdf_document_class_init (PdfDocumentClass *klass)
799 {
800         GObjectClass    *g_object_class = G_OBJECT_CLASS (klass);
801         EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
802
803         g_object_class->dispose = pdf_document_dispose;
804
805         ev_document_class->save = pdf_document_save;
806         ev_document_class->load = pdf_document_load;
807         ev_document_class->get_n_pages = pdf_document_get_n_pages;
808         ev_document_class->get_page = pdf_document_get_page;
809         ev_document_class->get_page_size = pdf_document_get_page_size;
810         ev_document_class->get_page_label = pdf_document_get_page_label;
811         ev_document_class->render = pdf_document_render;
812         ev_document_class->get_info = pdf_document_get_info;
813         ev_document_class->get_backend_info = pdf_document_get_backend_info;
814 }
815
816 /* EvDocumentSecurity */
817 static gboolean
818 pdf_document_has_document_security (EvDocumentSecurity *document_security)
819 {
820         /* FIXME: do we really need to have this? */
821         return FALSE;
822 }
823
824 static void
825 pdf_document_set_password (EvDocumentSecurity *document_security,
826                            const char         *password)
827 {
828         PdfDocument *document = PDF_DOCUMENT (document_security);
829
830         if (document->password)
831                 g_free (document->password);
832
833         document->password = g_strdup (password);
834 }
835
836 static void
837 pdf_document_security_iface_init (EvDocumentSecurityInterface *iface)
838 {
839         iface->has_document_security = pdf_document_has_document_security;
840         iface->set_password = pdf_document_set_password;
841 }
842
843 static gdouble
844 pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
845 {
846         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
847         int n_pages;
848
849         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
850
851         return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
852 }
853
854 static gboolean
855 pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
856                          int              n_pages)
857 {
858         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
859         gboolean result;
860
861         g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
862
863         if (pdf_document->font_info == NULL) { 
864                 pdf_document->font_info = poppler_font_info_new (pdf_document->document);
865         }
866
867         if (pdf_document->fonts_iter) {
868                 poppler_fonts_iter_free (pdf_document->fonts_iter);
869         }
870
871         pdf_document->fonts_scanned_pages += n_pages;
872
873         result = poppler_font_info_scan (pdf_document->font_info, n_pages,
874                                          &pdf_document->fonts_iter);
875         if (!result) {
876                 pdf_document->fonts_scanned_pages = 0;
877                 poppler_font_info_free (pdf_document->font_info);
878                 pdf_document->font_info = NULL; 
879         }
880
881         return result;
882 }
883
884 static const char *
885 font_type_to_string (PopplerFontType type)
886 {
887         switch (type) {
888                 case POPPLER_FONT_TYPE_TYPE1:
889                         return _("Type 1");
890                 case POPPLER_FONT_TYPE_TYPE1C:
891                         return _("Type 1C");
892                 case POPPLER_FONT_TYPE_TYPE3:
893                         return _("Type 3");
894                 case POPPLER_FONT_TYPE_TRUETYPE:
895                         return _("TrueType");
896                 case POPPLER_FONT_TYPE_CID_TYPE0:
897                         return _("Type 1 (CID)");
898                 case POPPLER_FONT_TYPE_CID_TYPE0C:
899                         return _("Type 1C (CID)");
900                 case POPPLER_FONT_TYPE_CID_TYPE2:
901                         return _("TrueType (CID)");
902                 default:
903                         return _("Unknown font type");
904         }
905 }
906
907 static void
908 pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
909                                GtkTreeModel    *model)
910 {
911         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
912         PopplerFontsIter *iter = pdf_document->fonts_iter;
913
914         g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
915
916         if (!iter)
917                 return;
918
919         do {
920                 GtkTreeIter list_iter;
921                 const char *name;
922                 const char *type;
923                 const char *embedded;
924                 char *details;
925                 
926                 name = poppler_fonts_iter_get_name (iter);
927
928                 if (name == NULL) {
929                         name = _("No name");
930                 }
931
932                 type = font_type_to_string (
933                         poppler_fonts_iter_get_font_type (iter));
934
935                 if (poppler_fonts_iter_is_embedded (iter)) {
936                         if (poppler_fonts_iter_is_subset (iter))
937                                 embedded = _("Embedded subset");
938                         else
939                                 embedded = _("Embedded");
940                 } else {
941                         embedded = _("Not embedded");
942                 }
943
944                 details = g_markup_printf_escaped ("%s\n%s", type, embedded);
945
946                 gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
947                 gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
948                                     EV_DOCUMENT_FONTS_COLUMN_NAME, name,
949                                     EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
950                                     -1);
951
952                 g_free (details);
953         } while (poppler_fonts_iter_next (iter));
954 }
955
956 static void
957 pdf_document_document_fonts_iface_init (EvDocumentFontsInterface *iface)
958 {
959         iface->fill_model = pdf_document_fonts_fill_model;
960         iface->scan = pdf_document_fonts_scan;
961         iface->get_progress = pdf_document_fonts_get_progress;
962 }
963
964 static gboolean
965 pdf_document_links_has_document_links (EvDocumentLinks *document_links)
966 {
967         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
968         PopplerIndexIter *iter;
969
970         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
971
972         iter = poppler_index_iter_new (pdf_document->document);
973         if (iter == NULL)
974                 return FALSE;
975         poppler_index_iter_free (iter);
976
977         return TRUE;
978 }
979
980 static EvLinkDest *
981 ev_link_dest_from_dest (PdfDocument *pdf_document,
982                         PopplerDest *dest)
983 {
984         EvLinkDest *ev_dest = NULL;
985         const char *unimplemented_dest = NULL;
986
987         g_assert (dest != NULL);
988
989         switch (dest->type) {
990                 case POPPLER_DEST_XYZ: {
991                         PopplerPage *poppler_page;
992                         double height;
993
994                         poppler_page = poppler_document_get_page (pdf_document->document,
995                                                                   MAX (0, dest->page_num - 1));
996                         poppler_page_get_size (poppler_page, NULL, &height);
997                         ev_dest = ev_link_dest_new_xyz (dest->page_num - 1,
998                                                         dest->left,
999                                                         height - MIN (height, dest->top),
1000                                                         dest->zoom,
1001                                                         dest->change_left,
1002                                                         dest->change_top,
1003                                                         dest->change_zoom);
1004                         g_object_unref (poppler_page);
1005                 }
1006                         break;
1007                 case POPPLER_DEST_FITB:
1008                 case POPPLER_DEST_FIT:
1009                         ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
1010                         break;
1011                 case POPPLER_DEST_FITBH:
1012                 case POPPLER_DEST_FITH: {
1013                         PopplerPage *poppler_page;
1014                         double height;
1015
1016                         poppler_page = poppler_document_get_page (pdf_document->document,
1017                                                                   MAX (0, dest->page_num - 1));
1018                         poppler_page_get_size (poppler_page, NULL, &height);
1019                         ev_dest = ev_link_dest_new_fith (dest->page_num - 1,
1020                                                          height - MIN (height, dest->top),
1021                                                          dest->change_top);
1022                         g_object_unref (poppler_page);
1023                 }
1024                         break;
1025                 case POPPLER_DEST_FITBV:
1026                 case POPPLER_DEST_FITV:
1027                         ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
1028                                                          dest->left,
1029                                                          dest->change_left);
1030                         break;
1031                 case POPPLER_DEST_FITR: {
1032                         PopplerPage *poppler_page;
1033                         double height;
1034
1035                         poppler_page = poppler_document_get_page (pdf_document->document,
1036                                                                   MAX (0, dest->page_num - 1));
1037                         poppler_page_get_size (poppler_page, NULL, &height);
1038                         ev_dest = ev_link_dest_new_fitr (dest->page_num - 1,
1039                                                          dest->left,
1040                                                          height - MIN (height, dest->bottom),
1041                                                          dest->right,
1042                                                          height - MIN (height, dest->top));
1043                         g_object_unref (poppler_page);
1044                 }
1045                         break;
1046                 case POPPLER_DEST_NAMED:
1047                         ev_dest = ev_link_dest_new_named (dest->named_dest);
1048                         break;
1049                 case POPPLER_DEST_UNKNOWN:
1050                         unimplemented_dest = "POPPLER_DEST_UNKNOWN";
1051                         break;
1052         }
1053
1054         if (unimplemented_dest) {
1055                 g_warning ("Unimplemented destination: %s, please post a "
1056                            "bug report in Evince bugzilla "
1057                            "(http://bugzilla.gnome.org) with a testcase.",
1058                            unimplemented_dest);
1059         }
1060
1061         if (!ev_dest)
1062                 ev_dest = ev_link_dest_new_page (dest->page_num - 1);
1063         
1064         return ev_dest;
1065 }
1066
1067 static EvLink *
1068 ev_link_from_action (PdfDocument   *pdf_document,
1069                      PopplerAction *action)
1070 {
1071         EvLink       *link = NULL;
1072         EvLinkAction *ev_action = NULL;
1073         const char   *unimplemented_action = NULL;
1074
1075         switch (action->type) {
1076                 case POPPLER_ACTION_NONE:
1077                         break;
1078                 case POPPLER_ACTION_GOTO_DEST: {
1079                         EvLinkDest *dest;
1080                         
1081                         dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest);
1082                         ev_action = ev_link_action_new_dest (dest);
1083                 }
1084                         break;
1085                 case POPPLER_ACTION_GOTO_REMOTE: {
1086                         EvLinkDest *dest;
1087                         
1088                         dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest);
1089                         ev_action = ev_link_action_new_remote (dest, 
1090                                                                action->goto_remote.file_name);
1091                         
1092                 }
1093                         break;
1094                 case POPPLER_ACTION_LAUNCH:
1095                         ev_action = ev_link_action_new_launch (action->launch.file_name,
1096                                                                action->launch.params);
1097                         break;
1098                 case POPPLER_ACTION_URI:
1099                         ev_action = ev_link_action_new_external_uri (action->uri.uri);
1100                         break;
1101                 case POPPLER_ACTION_NAMED:
1102                         ev_action = ev_link_action_new_named (action->named.named_dest);
1103                         break;
1104                 case POPPLER_ACTION_MOVIE:
1105                         unimplemented_action = "POPPLER_ACTION_MOVIE";
1106                         break;
1107 #if POPPLER_CHECK_VERSION (0, 13, 2)
1108                 case POPPLER_ACTION_RENDITION:
1109                         unimplemented_action = "POPPLER_ACTION_RENDITION";
1110                         break;
1111                 case POPPLER_ACTION_OCG_STATE:
1112                         unimplemented_action = "POPPLER_ACTION_OCG_STATE";
1113                         break;
1114 #endif
1115                 case POPPLER_ACTION_UNKNOWN:
1116                         unimplemented_action = "POPPLER_ACTION_UNKNOWN";
1117         }
1118         
1119         if (unimplemented_action) {
1120                 g_warning ("Unimplemented action: %s, please post a bug report "
1121                            "in Evince bugzilla (http://bugzilla.gnome.org) "
1122                            "with a testcase.", unimplemented_action);
1123         }
1124         
1125         link = ev_link_new (action->any.title, ev_action);
1126         
1127         return link;    
1128 }
1129
1130 static void
1131 build_tree (PdfDocument      *pdf_document,
1132             GtkTreeModel     *model,
1133             GtkTreeIter      *parent,
1134             PopplerIndexIter *iter)
1135 {
1136         
1137         do {
1138                 GtkTreeIter tree_iter;
1139                 PopplerIndexIter *child;
1140                 PopplerAction *action;
1141                 EvLink *link = NULL;
1142                 gboolean expand;
1143                 char *title_markup;
1144                 
1145                 action = poppler_index_iter_get_action (iter);
1146                 expand = poppler_index_iter_is_open (iter);
1147
1148                 if (!action)
1149                         continue;
1150
1151                 switch (action->type) {
1152                         case POPPLER_ACTION_GOTO_DEST: {
1153                                 /* For bookmarks, solve named destinations */
1154                                 if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
1155                                         PopplerDest *dest;
1156                                         EvLinkDest *ev_dest = NULL;
1157                                         EvLinkAction *ev_action;
1158                                         
1159                                         dest = poppler_document_find_dest (pdf_document->document,
1160                                                                            action->goto_dest.dest->named_dest);
1161                                         if (!dest) {
1162                                                 link = ev_link_from_action (pdf_document, action);
1163                                                 break;
1164                                         }
1165                                         
1166                                         ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1167                                         poppler_dest_free (dest);
1168                                         
1169                                         ev_action = ev_link_action_new_dest (ev_dest);
1170                                         link = ev_link_new (action->any.title, ev_action);
1171                                 } else {
1172                                         link = ev_link_from_action (pdf_document, action);
1173                                 }
1174                         }
1175                                 break;
1176                         default:
1177                                 link = ev_link_from_action (pdf_document, action);
1178                                 break;
1179                 }
1180                 
1181                 if (!link || strlen (ev_link_get_title (link)) <= 0) {
1182                         poppler_action_free (action);
1183                         if (link)
1184                                 g_object_unref (link);
1185                         
1186                         continue;
1187                 }
1188
1189                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
1190                 title_markup = g_markup_escape_text (ev_link_get_title (link), -1);
1191                 
1192                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
1193                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
1194                                     EV_DOCUMENT_LINKS_COLUMN_LINK, link,
1195                                     EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
1196                                     -1);
1197                 
1198                 g_free (title_markup);
1199                 g_object_unref (link);
1200                 
1201                 child = poppler_index_iter_get_child (iter);
1202                 if (child)
1203                         build_tree (pdf_document, model, &tree_iter, child);
1204                 poppler_index_iter_free (child);
1205                 poppler_action_free (action);
1206                 
1207         } while (poppler_index_iter_next (iter));
1208 }
1209
1210 static GtkTreeModel *
1211 pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1212 {
1213         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1214         GtkTreeModel *model = NULL;
1215         PopplerIndexIter *iter;
1216         
1217         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1218
1219         iter = poppler_index_iter_new (pdf_document->document);
1220         /* Create the model if we have items*/
1221         if (iter != NULL) {
1222                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1223                                                              G_TYPE_STRING,
1224                                                              G_TYPE_OBJECT,
1225                                                              G_TYPE_BOOLEAN,
1226                                                              G_TYPE_STRING);
1227                 build_tree (pdf_document, model, NULL, iter);
1228                 poppler_index_iter_free (iter);
1229         }
1230         
1231         return model;
1232 }
1233
1234 static GList *
1235 pdf_document_links_get_links (EvDocumentLinks *document_links,
1236                               EvPage          *page)
1237 {
1238         PdfDocument *pdf_document;
1239         PopplerPage *poppler_page;
1240         GList *retval = NULL;
1241         GList *mapping_list;
1242         GList *list;
1243         double height;
1244
1245         pdf_document = PDF_DOCUMENT (document_links);
1246         poppler_page = POPPLER_PAGE (page->backend_page);
1247         mapping_list = poppler_page_get_link_mapping (poppler_page);
1248         poppler_page_get_size (poppler_page, NULL, &height);
1249
1250         for (list = mapping_list; list; list = list->next) {
1251                 PopplerLinkMapping *link_mapping;
1252                 EvMapping *ev_link_mapping;
1253
1254                 link_mapping = (PopplerLinkMapping *)list->data;
1255                 ev_link_mapping = g_new (EvMapping, 1);
1256                 ev_link_mapping->data = ev_link_from_action (pdf_document,
1257                                                              link_mapping->action);
1258                 ev_link_mapping->area.x1 = link_mapping->area.x1;
1259                 ev_link_mapping->area.x2 = link_mapping->area.x2;
1260                 /* Invert this for X-style coordinates */
1261                 ev_link_mapping->area.y1 = height - link_mapping->area.y2;
1262                 ev_link_mapping->area.y2 = height - link_mapping->area.y1;
1263
1264                 retval = g_list_prepend (retval, ev_link_mapping);
1265         }
1266
1267         poppler_page_free_link_mapping (mapping_list);
1268
1269         return g_list_reverse (retval);
1270 }
1271
1272 static EvLinkDest *
1273 pdf_document_links_find_link_dest (EvDocumentLinks  *document_links,
1274                                    const gchar      *link_name)
1275 {
1276         PdfDocument *pdf_document;
1277         PopplerDest *dest;
1278         EvLinkDest *ev_dest = NULL;
1279
1280         pdf_document = PDF_DOCUMENT (document_links);
1281         dest = poppler_document_find_dest (pdf_document->document,
1282                                            link_name);
1283         if (dest) {
1284                 ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1285                 poppler_dest_free (dest);
1286         }
1287
1288         return ev_dest;
1289 }
1290
1291 static void
1292 pdf_document_document_links_iface_init (EvDocumentLinksInterface *iface)
1293 {
1294         iface->has_document_links = pdf_document_links_has_document_links;
1295         iface->get_links_model = pdf_document_links_get_links_model;
1296         iface->get_links = pdf_document_links_get_links;
1297         iface->find_link_dest = pdf_document_links_find_link_dest;
1298 }
1299
1300 static GList *
1301 pdf_document_images_get_image_mapping (EvDocumentImages *document_images,
1302                                        EvPage           *page)
1303 {
1304         GList *retval = NULL;
1305         PdfDocument *pdf_document;
1306         PopplerPage *poppler_page;
1307         GList *mapping_list;
1308         GList *list;
1309
1310         pdf_document = PDF_DOCUMENT (document_images);
1311         poppler_page = POPPLER_PAGE (page->backend_page);
1312         mapping_list = poppler_page_get_image_mapping (poppler_page);
1313
1314         for (list = mapping_list; list; list = list->next) {
1315                 PopplerImageMapping *image_mapping;
1316                 EvMapping *ev_image_mapping;
1317
1318                 image_mapping = (PopplerImageMapping *)list->data;
1319
1320                 ev_image_mapping = g_new (EvMapping, 1);
1321                 
1322                 ev_image_mapping->data = ev_image_new (page->index, image_mapping->image_id);
1323                 ev_image_mapping->area.x1 = image_mapping->area.x1;
1324                 ev_image_mapping->area.y1 = image_mapping->area.y1;
1325                 ev_image_mapping->area.x2 = image_mapping->area.x2;
1326                 ev_image_mapping->area.y2 = image_mapping->area.y2;
1327
1328                 retval = g_list_prepend (retval, ev_image_mapping);
1329         }
1330
1331         poppler_page_free_image_mapping (mapping_list);
1332
1333         return g_list_reverse (retval);
1334 }
1335
1336 GdkPixbuf *
1337 pdf_document_images_get_image (EvDocumentImages *document_images,
1338                                EvImage          *image)
1339 {
1340         GdkPixbuf       *retval = NULL;
1341         PdfDocument     *pdf_document;
1342         PopplerPage     *poppler_page;
1343         cairo_surface_t *surface;
1344
1345         pdf_document = PDF_DOCUMENT (document_images);
1346         poppler_page = poppler_document_get_page (pdf_document->document,
1347                                                   ev_image_get_page (image));
1348
1349         surface = poppler_page_get_image (poppler_page, ev_image_get_id (image));
1350         if (surface) {
1351                 retval = ev_document_misc_pixbuf_from_surface (surface);
1352                 cairo_surface_destroy (surface);
1353         }
1354
1355         g_object_unref (poppler_page);
1356
1357         return retval;
1358 }
1359
1360 static void
1361 pdf_document_document_images_iface_init (EvDocumentImagesInterface *iface)
1362 {
1363         iface->get_image_mapping = pdf_document_images_get_image_mapping;
1364         iface->get_image = pdf_document_images_get_image;
1365 }
1366
1367 static GdkPixbuf *
1368 make_thumbnail_for_page (PopplerPage     *poppler_page,
1369                          EvRenderContext *rc,
1370                          gint             width,
1371                          gint             height)
1372 {
1373         GdkPixbuf *pixbuf;
1374
1375 #ifdef POPPLER_WITH_GDK
1376         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
1377                                  width, height);
1378         gdk_pixbuf_fill (pixbuf, 0xffffffff);
1379
1380         ev_document_fc_mutex_lock ();
1381         poppler_page_render_to_pixbuf (poppler_page, 0, 0,
1382                                        width, height,
1383                                        rc->scale, rc->rotation, pixbuf);
1384         ev_document_fc_mutex_unlock ();
1385 #else
1386         cairo_surface_t *surface;
1387
1388         ev_document_fc_mutex_lock ();
1389         surface = pdf_page_render (poppler_page, width, height, rc);
1390         ev_document_fc_mutex_unlock ();
1391         
1392         pixbuf = ev_document_misc_pixbuf_from_surface (surface);
1393         cairo_surface_destroy (surface);
1394 #endif /* POPPLER_WITH_GDK */
1395
1396         return pixbuf;
1397 }
1398
1399 static GdkPixbuf *
1400 pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
1401                                        EvRenderContext      *rc, 
1402                                        gboolean              border)
1403 {
1404         PdfDocument *pdf_document = PDF_DOCUMENT (document_thumbnails);
1405         PopplerPage *poppler_page;
1406         GdkPixbuf *pixbuf = NULL;
1407         GdkPixbuf *border_pixbuf;
1408         gint width, height;
1409
1410         poppler_page = POPPLER_PAGE (rc->page->backend_page);
1411
1412         pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
1413                                                 rc, &width, &height);
1414         
1415 #ifdef POPPLER_WITH_GDK
1416         pixbuf = poppler_page_get_thumbnail_pixbuf (poppler_page);
1417 #else
1418         cairo_surface_t *surface;
1419         
1420         surface = poppler_page_get_thumbnail (poppler_page);
1421         if (surface) {
1422                 pixbuf = ev_document_misc_pixbuf_from_surface (surface);
1423                 cairo_surface_destroy (surface);
1424         }
1425 #endif /* POPPLER_WITH_GDK */
1426
1427         if (pixbuf != NULL) {
1428                 int thumb_width = (rc->rotation == 90 || rc->rotation == 270) ?
1429                         gdk_pixbuf_get_height (pixbuf) :
1430                         gdk_pixbuf_get_width (pixbuf);
1431
1432                 if (thumb_width == width) {
1433                         GdkPixbuf *rotated_pixbuf;
1434
1435                         rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
1436                                                                    (GdkPixbufRotation) (360 - rc->rotation));
1437                         g_object_unref (pixbuf);
1438                         pixbuf = rotated_pixbuf;
1439                 } else {
1440                         /* The provided thumbnail has a different size */
1441                         g_object_unref (pixbuf);
1442                         pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height);
1443                 }
1444         } else {
1445                 /* There is no provided thumbnail. We need to make one. */
1446                 pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height);
1447         }
1448
1449         if (border && pixbuf) {
1450                 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
1451                 g_object_unref (pixbuf);
1452                 pixbuf = border_pixbuf;
1453         }               
1454
1455         return pixbuf;
1456 }
1457
1458 static void
1459 pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
1460                                         EvRenderContext      *rc,
1461                                         gint                 *width,
1462                                         gint                 *height)
1463 {
1464         double page_width, page_height;
1465         
1466         poppler_page_get_size (POPPLER_PAGE (rc->page->backend_page),
1467                                &page_width, &page_height);
1468         
1469         *width = MAX ((gint)(page_width * rc->scale + 0.5), 1);
1470         *height = MAX ((gint)(page_height * rc->scale + 0.5), 1);
1471
1472         if (rc->rotation == 90 || rc->rotation == 270) {
1473                 gint  temp;
1474
1475                 temp = *width;
1476                 *width = *height;
1477                 *height = temp;
1478         }
1479 }
1480
1481 static void
1482 pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface)
1483 {
1484         iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
1485         iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
1486 }
1487
1488
1489 static GList *
1490 pdf_document_find_find_text (EvDocumentFind *document_find,
1491                              EvPage         *page,
1492                              const gchar    *text,
1493                              gboolean        case_sensitive)
1494 {
1495         GList *matches, *l;
1496         PopplerPage *poppler_page;
1497         gdouble height;
1498         GList *retval = NULL;
1499
1500         g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
1501         g_return_val_if_fail (text != NULL, NULL);
1502
1503         poppler_page = POPPLER_PAGE (page->backend_page);
1504         
1505         matches = poppler_page_find_text (poppler_page, text);
1506         if (!matches)
1507                 return NULL;
1508
1509         poppler_page_get_size (poppler_page, NULL, &height);
1510         for (l = matches; l && l->data; l = g_list_next (l)) {
1511                 PopplerRectangle *rect = (PopplerRectangle *)l->data;
1512                 EvRectangle      *ev_rect;
1513
1514                 ev_rect = ev_rectangle_new ();
1515                 ev_rect->x1 = rect->x1;
1516                 ev_rect->x2 = rect->x2;
1517                 /* Invert this for X-style coordinates */
1518                 ev_rect->y1 = height - rect->y2;
1519                 ev_rect->y2 = height - rect->y1;
1520
1521                 retval = g_list_prepend (retval, ev_rect);
1522         }
1523
1524         g_list_foreach (matches, (GFunc)poppler_rectangle_free, NULL);
1525         g_list_free (matches);
1526
1527         return g_list_reverse (retval);
1528 }
1529
1530 static void
1531 pdf_document_find_iface_init (EvDocumentFindInterface *iface)
1532 {
1533         iface->find_text = pdf_document_find_find_text;
1534 }
1535
1536 static void
1537 pdf_print_context_free (PdfPrintContext *ctx)
1538 {
1539         if (!ctx)
1540                 return;
1541
1542 #ifdef HAVE_CAIRO_PRINT
1543         if (ctx->cr) {
1544                 cairo_destroy (ctx->cr);
1545                 ctx->cr = NULL;
1546         }
1547 #else
1548         if (ctx->ps_file) {
1549                 poppler_ps_file_free (ctx->ps_file);
1550                 ctx->ps_file = NULL;
1551         }
1552 #endif
1553         g_free (ctx);
1554 }
1555
1556 static void
1557 pdf_document_file_exporter_begin (EvFileExporter        *exporter,
1558                                   EvFileExporterContext *fc)
1559 {
1560         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1561         PdfPrintContext *ctx;
1562 #ifdef HAVE_CAIRO_PRINT
1563         gdouble width, height;
1564         cairo_surface_t *surface = NULL;
1565 #endif
1566         
1567         if (pdf_document->print_ctx)
1568                 pdf_print_context_free (pdf_document->print_ctx);
1569         pdf_document->print_ctx = g_new0 (PdfPrintContext, 1);
1570         ctx = pdf_document->print_ctx;
1571         ctx->format = fc->format;
1572         
1573 #ifdef HAVE_CAIRO_PRINT
1574         ctx->pages_per_sheet = CLAMP (fc->pages_per_sheet, 1, 16);
1575
1576         ctx->paper_width = fc->paper_width;
1577         ctx->paper_height = fc->paper_height;
1578         
1579         switch (fc->pages_per_sheet) {
1580                 default:
1581                 case 1:
1582                         ctx->pages_x = 1;
1583                         ctx->pages_y = 1;
1584                         break;
1585                 case 2:
1586                         ctx->pages_x = 1;
1587                         ctx->pages_y = 2;
1588                         break;
1589                 case 4:
1590                         ctx->pages_x = 2;
1591                         ctx->pages_y = 2;
1592                         break;
1593                 case 6:
1594                         ctx->pages_x = 2;
1595                         ctx->pages_y = 3;
1596                         break;
1597                 case 9:
1598                         ctx->pages_x = 3;
1599                         ctx->pages_y = 3;
1600                         break;
1601                 case 16:
1602                         ctx->pages_x = 4;
1603                         ctx->pages_y = 4;
1604                         break;
1605         }
1606
1607         ctx->pages_printed = 0;
1608         
1609         switch (fc->format) {
1610                 case EV_FILE_FORMAT_PS:
1611 #ifdef HAVE_CAIRO_PS
1612                         surface = cairo_ps_surface_create (fc->filename, fc->paper_width, fc->paper_height);
1613 #endif
1614                         break;
1615                 case EV_FILE_FORMAT_PDF:
1616 #ifdef HAVE_CAIRO_PDF
1617                         surface = cairo_pdf_surface_create (fc->filename, fc->paper_width, fc->paper_height);
1618 #endif
1619                         break;
1620                 default:
1621                         g_assert_not_reached ();
1622         }
1623
1624         ctx->cr = cairo_create (surface);
1625         cairo_surface_destroy (surface);
1626
1627 #else /* HAVE_CAIRO_PRINT */
1628         if (ctx->format == EV_FILE_FORMAT_PS) {
1629                 ctx->ps_file = poppler_ps_file_new (pdf_document->document,
1630                                                     fc->filename, fc->first_page,
1631                                                     fc->last_page - fc->first_page + 1);
1632                 poppler_ps_file_set_paper_size (ctx->ps_file, fc->paper_width, fc->paper_height);
1633                 poppler_ps_file_set_duplex (ctx->ps_file, fc->duplex);
1634         }
1635 #endif /* HAVE_CAIRO_PRINT */
1636 }
1637
1638 static void
1639 pdf_document_file_exporter_begin_page (EvFileExporter *exporter)
1640 {
1641         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1642         PdfPrintContext *ctx = pdf_document->print_ctx;
1643         
1644         g_return_if_fail (pdf_document->print_ctx != NULL);
1645
1646         ctx->pages_printed = 0;
1647         
1648 #ifdef HAVE_CAIRO_PRINT
1649         if (ctx->paper_width > ctx->paper_height) {
1650                 if (ctx->format == EV_FILE_FORMAT_PS) {
1651                         cairo_ps_surface_set_size (cairo_get_target (ctx->cr),
1652                                                    ctx->paper_height,
1653                                                    ctx->paper_width);
1654                 } else if (ctx->format == EV_FILE_FORMAT_PDF) {
1655                         cairo_pdf_surface_set_size (cairo_get_target (ctx->cr),
1656                                                     ctx->paper_height,
1657                                                     ctx->paper_width);
1658                 }
1659         }
1660 #endif /* HAVE_CAIRO_PRINT */
1661 }
1662
1663 static void
1664 pdf_document_file_exporter_do_page (EvFileExporter  *exporter,
1665                                     EvRenderContext *rc)
1666 {
1667         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1668         PdfPrintContext *ctx = pdf_document->print_ctx;
1669         PopplerPage *poppler_page;
1670 #ifdef HAVE_CAIRO_PRINT
1671         gdouble  page_width, page_height;
1672         gint     x, y;
1673         gboolean rotate;
1674         gdouble  width, height;
1675         gdouble  pwidth, pheight;
1676         gdouble  xscale, yscale;
1677 #endif
1678
1679         g_return_if_fail (pdf_document->print_ctx != NULL);
1680
1681         poppler_page = POPPLER_PAGE (rc->page->backend_page);
1682         
1683 #ifdef HAVE_CAIRO_PRINT
1684         x = (ctx->pages_printed % ctx->pages_per_sheet) % ctx->pages_x;
1685         y = (ctx->pages_printed % ctx->pages_per_sheet) / ctx->pages_x;
1686         poppler_page_get_size (poppler_page, &page_width, &page_height);
1687
1688         if (page_width > page_height && page_width > ctx->paper_width) {
1689                 rotate = TRUE;
1690         } else {
1691                 rotate = FALSE;
1692         }
1693
1694         /* Use always portrait mode and rotate when necessary */
1695         if (ctx->paper_width > ctx->paper_height) {
1696                 width = ctx->paper_height;
1697                 height = ctx->paper_width;
1698                 rotate = !rotate;
1699         } else {
1700                 width = ctx->paper_width;
1701                 height = ctx->paper_height;
1702         }
1703
1704         if (ctx->pages_per_sheet == 2 || ctx->pages_per_sheet == 6) {
1705                 rotate = !rotate;
1706         }       
1707
1708         if (rotate) {
1709                 gint tmp1;
1710                 gdouble tmp2;
1711
1712                 tmp1 = x;
1713                 x = y;
1714                 y = tmp1;
1715
1716                 tmp2 = page_width;
1717                 page_width = page_height;
1718                 page_height = tmp2;
1719         }
1720
1721         pwidth = width / ctx->pages_x;
1722         pheight = height / ctx->pages_y;
1723
1724         if ((page_width > pwidth || page_height > pheight) ||
1725             (page_width < pwidth && page_height < pheight)) {
1726                 xscale = pwidth / page_width;
1727                 yscale = pheight / page_height;
1728                 
1729                 if (yscale < xscale) {
1730                         xscale = yscale;
1731                 } else {
1732                         yscale = xscale;
1733                 }
1734                 
1735         } else {        
1736                 xscale = yscale = 1;
1737         }
1738
1739         /* TODO: center */
1740
1741         cairo_save (ctx->cr);
1742         if (rotate) {
1743                 cairo_matrix_t matrix;
1744                 
1745                 cairo_translate (ctx->cr, (2 * y + 1) * pwidth, 0);
1746                 cairo_matrix_init (&matrix,
1747                                    0,  1,
1748                                    -1,  0,
1749                                    0,  0);
1750                 cairo_transform (ctx->cr, &matrix);
1751         }
1752         
1753         cairo_translate (ctx->cr,
1754                          x * (rotate ? pheight : pwidth),
1755                          y * (rotate ? pwidth : pheight));
1756         cairo_scale (ctx->cr, xscale, yscale);
1757
1758         poppler_page_render_for_printing (poppler_page, ctx->cr);
1759
1760         ctx->pages_printed++;
1761                         
1762         cairo_restore (ctx->cr);
1763 #else /* HAVE_CAIRO_PRINT */
1764         if (ctx->format == EV_FILE_FORMAT_PS)
1765                 poppler_page_render_to_ps (poppler_page, ctx->ps_file);
1766 #endif /* HAVE_CAIRO_PRINT */
1767 }
1768
1769 static void
1770 pdf_document_file_exporter_end_page (EvFileExporter *exporter)
1771 {
1772         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1773         PdfPrintContext *ctx = pdf_document->print_ctx;
1774         
1775         g_return_if_fail (pdf_document->print_ctx != NULL);
1776
1777 #ifdef HAVE_CAIRO_PRINT
1778         cairo_show_page (ctx->cr);
1779 #endif
1780 }
1781
1782 static void
1783 pdf_document_file_exporter_end (EvFileExporter *exporter)
1784 {
1785         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1786
1787         pdf_print_context_free (pdf_document->print_ctx);
1788         pdf_document->print_ctx = NULL;
1789 }
1790
1791 static EvFileExporterCapabilities
1792 pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
1793 {
1794         return  (EvFileExporterCapabilities) (
1795                 EV_FILE_EXPORTER_CAN_PAGE_SET |
1796                 EV_FILE_EXPORTER_CAN_COPIES |
1797                 EV_FILE_EXPORTER_CAN_COLLATE |
1798                 EV_FILE_EXPORTER_CAN_REVERSE |
1799                 EV_FILE_EXPORTER_CAN_SCALE |
1800 #ifdef HAVE_CAIRO_PRINT
1801                 EV_FILE_EXPORTER_CAN_NUMBER_UP |
1802 #endif
1803                 
1804 #ifdef HAVE_CAIRO_PDF
1805                 EV_FILE_EXPORTER_CAN_GENERATE_PDF |
1806 #endif
1807                 EV_FILE_EXPORTER_CAN_GENERATE_PS);
1808 }
1809
1810 static void
1811 pdf_document_file_exporter_iface_init (EvFileExporterInterface *iface)
1812 {
1813         iface->begin = pdf_document_file_exporter_begin;
1814         iface->begin_page = pdf_document_file_exporter_begin_page;
1815         iface->do_page = pdf_document_file_exporter_do_page;
1816         iface->end_page = pdf_document_file_exporter_end_page;
1817         iface->end = pdf_document_file_exporter_end;
1818         iface->get_capabilities = pdf_document_file_exporter_get_capabilities;
1819 }
1820
1821 /* EvDocumentPrint */
1822 static void
1823 pdf_document_print_print_page (EvDocumentPrint *document,
1824                                EvPage          *page,
1825                                cairo_t         *cr)
1826 {
1827         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1828
1829         poppler_page_render_for_printing (POPPLER_PAGE (page->backend_page), cr);
1830 }
1831
1832 static void
1833 pdf_document_document_print_iface_init (EvDocumentPrintInterface *iface)
1834 {
1835         iface->print_page = pdf_document_print_print_page;
1836 }
1837
1838 static void
1839 pdf_selection_render_selection (EvSelection      *selection,
1840                                 EvRenderContext  *rc,
1841                                 cairo_surface_t **surface,
1842                                 EvRectangle      *points,
1843                                 EvRectangle      *old_points,
1844                                 EvSelectionStyle  style,
1845                                 GdkColor         *text,
1846                                 GdkColor         *base)
1847 {
1848         PopplerPage *poppler_page;
1849         cairo_t *cr;
1850         PopplerColor text_color, base_color;
1851         double width_points, height_points;
1852         gint width, height;
1853
1854         poppler_page = POPPLER_PAGE (rc->page->backend_page);
1855
1856         poppler_page_get_size (poppler_page,
1857                                &width_points, &height_points);
1858         width = (int) ((width_points * rc->scale) + 0.5);
1859         height = (int) ((height_points * rc->scale) + 0.5);
1860
1861         text_color.red = text->red;
1862         text_color.green = text->green;
1863         text_color.blue = text->blue;
1864
1865         base_color.red = base->red;
1866         base_color.green = base->green;
1867         base_color.blue = base->blue;
1868
1869         if (*surface == NULL) {
1870                 *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1871                                                        width, height);
1872                 
1873         }
1874
1875         cr = cairo_create (*surface);
1876         cairo_scale (cr, rc->scale, rc->scale);
1877         cairo_surface_set_device_offset (*surface, 0, 0);
1878         memset (cairo_image_surface_get_data (*surface), 0x00,
1879                 cairo_image_surface_get_height (*surface) *
1880                 cairo_image_surface_get_stride (*surface));
1881         poppler_page_render_selection (poppler_page,
1882                                        cr,
1883                                        (PopplerRectangle *)points,
1884                                        (PopplerRectangle *)old_points,
1885                                        (PopplerSelectionStyle)style,
1886                                        &text_color,
1887                                        &base_color);
1888         cairo_destroy (cr);
1889 }
1890
1891 static gchar *
1892 pdf_selection_get_selected_text (EvSelection     *selection,
1893                                  EvPage          *page,
1894                                  EvSelectionStyle style,
1895                                  EvRectangle     *points)
1896 {
1897         PopplerPage *poppler_page;
1898         PopplerRectangle r;
1899         double height;
1900         char *retval;
1901         
1902         poppler_page = POPPLER_PAGE (page->backend_page);
1903
1904         poppler_page_get_size (poppler_page, NULL, &height);
1905         r.x1 = points->x1;
1906         r.y1 = height - points->y2;
1907         r.x2 = points->x2;
1908         r.y2 = height - points->y1;
1909
1910         retval = poppler_page_get_text (poppler_page,
1911                                         (PopplerSelectionStyle)style,
1912                                         &r);
1913
1914         return retval;
1915 }
1916
1917 static GdkRegion *
1918 create_gdk_region_from_poppler_region (GList *region)
1919 {
1920         GList *l;
1921         GdkRegion *retval;
1922         
1923         retval = gdk_region_new ();
1924         
1925         for (l = region; l; l = g_list_next (l)) {
1926                 PopplerRectangle *rectangle;
1927                 GdkRectangle      rect;
1928                 
1929                 rectangle = (PopplerRectangle *)l->data;
1930                 
1931                 rect.x = (gint) rectangle->x1;
1932                 rect.y = (gint) rectangle->y1;
1933                 rect.width  = (gint) (rectangle->x2 - rectangle->x1);
1934                 rect.height = (gint) (rectangle->y2 - rectangle->y1);
1935                 gdk_region_union_with_rect (retval, &rect);
1936                 
1937                 poppler_rectangle_free (rectangle);
1938         }
1939
1940         return retval;
1941 }
1942
1943 static GdkRegion *
1944 pdf_selection_get_selection_region (EvSelection     *selection,
1945                                     EvRenderContext *rc,
1946                                     EvSelectionStyle style,
1947                                     EvRectangle     *points)
1948 {
1949         PopplerPage *poppler_page;
1950         GdkRegion   *retval;
1951         GList       *region;
1952
1953         poppler_page = POPPLER_PAGE (rc->page->backend_page);
1954         
1955         region = poppler_page_get_selection_region (poppler_page,
1956                                                     rc->scale,
1957                                                     (PopplerSelectionStyle)style,
1958                                                     (PopplerRectangle *) points);
1959         retval = create_gdk_region_from_poppler_region (region);
1960         g_list_free (region);
1961         
1962         return retval;
1963 }
1964
1965 static GdkRegion *
1966 pdf_selection_get_selection_map (EvSelection *selection,
1967                                  EvPage      *page)
1968 {
1969         PopplerPage *poppler_page;
1970         PopplerRectangle points;
1971         GList *region;
1972         GdkRegion *retval;
1973
1974         poppler_page = POPPLER_PAGE (page->backend_page);
1975
1976         points.x1 = 0.0;
1977         points.y1 = 0.0;
1978         poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
1979         
1980         region = poppler_page_get_selection_region (poppler_page, 1.0,
1981                                                     POPPLER_SELECTION_GLYPH,
1982                                                     &points);
1983         retval = create_gdk_region_from_poppler_region (region);
1984         g_list_free (region);
1985
1986         return retval;
1987 }
1988
1989 static void
1990 pdf_selection_iface_init (EvSelectionInterface *iface)
1991 {
1992         iface->render_selection = pdf_selection_render_selection;
1993         iface->get_selected_text = pdf_selection_get_selected_text;
1994         iface->get_selection_region = pdf_selection_get_selection_region;
1995         iface->get_selection_map = pdf_selection_get_selection_map;
1996 }
1997
1998 /* Page Transitions */
1999 static gdouble
2000 pdf_document_get_page_duration (EvDocumentTransition *trans,
2001                                 gint                  page)
2002 {
2003         PdfDocument *pdf_document;
2004         PopplerPage *poppler_page;
2005         gdouble      duration = -1;
2006
2007         pdf_document = PDF_DOCUMENT (trans);
2008         poppler_page = poppler_document_get_page (pdf_document->document, page);
2009         if (!poppler_page)
2010                 return -1;
2011
2012         duration = poppler_page_get_duration (poppler_page);
2013         g_object_unref (poppler_page);
2014
2015         return duration;
2016 }
2017
2018 static EvTransitionEffect *
2019 pdf_document_get_effect (EvDocumentTransition *trans,
2020                          gint                  page)
2021 {
2022         PdfDocument            *pdf_document;
2023         PopplerPage            *poppler_page;
2024         PopplerPageTransition  *page_transition;
2025         EvTransitionEffect     *effect;
2026
2027         pdf_document = PDF_DOCUMENT (trans);
2028         poppler_page = poppler_document_get_page (pdf_document->document, page);
2029
2030         if (!poppler_page)
2031                 return NULL;
2032
2033         page_transition = poppler_page_get_transition (poppler_page);
2034
2035         if (!page_transition) {
2036                 g_object_unref (poppler_page);
2037                 return NULL;
2038         }
2039
2040         /* enums in PopplerPageTransition match the EvTransitionEffect ones */
2041         effect = ev_transition_effect_new ((EvTransitionEffectType) page_transition->type,
2042                                            "alignment", page_transition->alignment,
2043                                            "direction", page_transition->direction,
2044                                            "duration", page_transition->duration,
2045                                            "angle", page_transition->angle,
2046                                            "scale", page_transition->scale,
2047                                            "rectangular", page_transition->rectangular,
2048                                            NULL);
2049
2050         poppler_page_transition_free (page_transition);
2051         g_object_unref (poppler_page);
2052
2053         return effect;
2054 }
2055
2056 static void
2057 pdf_document_page_transition_iface_init (EvDocumentTransitionInterface *iface)
2058 {
2059         iface->get_page_duration = pdf_document_get_page_duration;
2060         iface->get_effect = pdf_document_get_effect;
2061 }
2062
2063 /* Forms */
2064 static void
2065 pdf_document_get_crop_box (EvDocument  *document, 
2066                            int          page, 
2067                            EvRectangle *rect)
2068 {
2069         PdfDocument *pdf_document;
2070         PopplerPage *poppler_page;
2071         PopplerRectangle poppler_rect;
2072
2073         pdf_document = PDF_DOCUMENT (document);
2074         poppler_page = poppler_document_get_page (pdf_document->document, page);
2075         poppler_page_get_crop_box (poppler_page, &poppler_rect);
2076         rect->x1 = poppler_rect.x1;
2077         rect->x2 = poppler_rect.x2;
2078         rect->y1 = poppler_rect.y1;
2079         rect->y2 = poppler_rect.y2;
2080 }
2081
2082 static EvFormField *
2083 ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
2084 {
2085         EvFormField *ev_field = NULL;
2086         gint         id;
2087         gdouble      font_size;
2088         gboolean     is_read_only;
2089
2090         id = poppler_form_field_get_id (poppler_field);
2091         font_size = poppler_form_field_get_font_size (poppler_field);
2092         is_read_only = poppler_form_field_is_read_only (poppler_field);
2093
2094         switch (poppler_form_field_get_field_type (poppler_field)) {
2095                 case POPPLER_FORM_FIELD_TEXT: {
2096                         EvFormFieldText    *field_text;
2097                         EvFormFieldTextType ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
2098
2099                         switch (poppler_form_field_text_get_text_type (poppler_field)) {
2100                                 case POPPLER_FORM_TEXT_NORMAL:
2101                                         ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
2102                                         break;
2103                                 case POPPLER_FORM_TEXT_MULTILINE:
2104                                         ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
2105                                         break;
2106                                 case POPPLER_FORM_TEXT_FILE_SELECT:
2107                                         ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
2108                                         break;
2109                         }
2110                         
2111                         ev_field = ev_form_field_text_new (id, ev_text_type);
2112                         field_text = EV_FORM_FIELD_TEXT (ev_field);
2113
2114                         field_text->do_spell_check = poppler_form_field_text_do_spell_check (poppler_field);
2115                         field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
2116                         field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
2117                         field_text->is_password = poppler_form_field_text_is_password (poppler_field);
2118                         field_text->max_len = poppler_form_field_text_get_max_len (poppler_field);
2119                         field_text->text = poppler_form_field_text_get_text (poppler_field);
2120
2121                 }
2122                         break;
2123                 case POPPLER_FORM_FIELD_BUTTON: {
2124                         EvFormFieldButton    *field_button;
2125                         EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2126
2127                         switch (poppler_form_field_button_get_button_type (poppler_field)) {
2128                                 case POPPLER_FORM_BUTTON_PUSH:
2129                                         ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2130                                         break;
2131                                 case POPPLER_FORM_BUTTON_CHECK:
2132                                         ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
2133                                         break;
2134                                 case POPPLER_FORM_BUTTON_RADIO:
2135                                         ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
2136                                         break;
2137                         }
2138
2139                         ev_field = ev_form_field_button_new (id, ev_button_type);
2140                         field_button = EV_FORM_FIELD_BUTTON (ev_field);
2141                         
2142                         field_button->state = poppler_form_field_button_get_state (poppler_field);
2143                 }
2144                         break;
2145                 case POPPLER_FORM_FIELD_CHOICE: {
2146                         EvFormFieldChoice    *field_choice;
2147                         EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2148
2149                         switch (poppler_form_field_choice_get_choice_type (poppler_field)) {
2150                                 case POPPLER_FORM_CHOICE_COMBO:
2151                                         ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2152                                         break;
2153                                 case EV_FORM_FIELD_CHOICE_LIST:
2154                                         ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
2155                                         break;
2156                         }
2157
2158                         ev_field = ev_form_field_choice_new (id, ev_choice_type);
2159                         field_choice = EV_FORM_FIELD_CHOICE (ev_field);
2160
2161                         field_choice->is_editable = poppler_form_field_choice_is_editable (poppler_field);
2162                         field_choice->multi_select = poppler_form_field_choice_can_select_multiple (poppler_field);
2163                         field_choice->do_spell_check = poppler_form_field_choice_do_spell_check (poppler_field);
2164                         field_choice->commit_on_sel_change = poppler_form_field_choice_commit_on_change (poppler_field);
2165
2166                         /* TODO: we need poppler_form_field_choice_get_selected_items in poppler 
2167                         field_choice->selected_items = poppler_form_field_choice_get_selected_items (poppler_field);*/
2168                         if (field_choice->is_editable)
2169                                 field_choice->text = poppler_form_field_choice_get_text (poppler_field);
2170                 }
2171                         break;
2172                 case POPPLER_FORM_FIELD_SIGNATURE:
2173                         /* TODO */
2174                         ev_field = ev_form_field_signature_new (id);
2175                         break;
2176                 case POPPLER_FORM_FIELD_UNKNOWN:
2177                         return NULL;
2178         }
2179
2180         ev_field->font_size = font_size;
2181         ev_field->is_read_only = is_read_only;
2182
2183         return ev_field;
2184 }
2185
2186 static GList *
2187 pdf_document_forms_get_form_fields (EvDocumentForms *document, 
2188                                     EvPage          *page)
2189 {
2190         PopplerPage *poppler_page;
2191         GList *retval = NULL;
2192         GList *fields;
2193         GList *list;
2194         double height;
2195
2196         g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
2197         
2198         poppler_page = POPPLER_PAGE (page->backend_page);
2199         fields = poppler_page_get_form_field_mapping (poppler_page);
2200         poppler_page_get_size (poppler_page, NULL, &height);
2201
2202         for (list = fields; list; list = list->next) {
2203                 PopplerFormFieldMapping *mapping;
2204                 EvMapping *field_mapping;
2205                 EvFormField *ev_field;
2206
2207                 mapping = (PopplerFormFieldMapping *)list->data;
2208
2209                 ev_field = ev_form_field_from_poppler_field (mapping->field);
2210                 if (!ev_field)
2211                         continue;
2212
2213                 field_mapping = g_new0 (EvMapping, 1);
2214                 field_mapping->area.x1 = mapping->area.x1;
2215                 field_mapping->area.x2 = mapping->area.x2;
2216                 field_mapping->area.y1 = height - mapping->area.y2;
2217                 field_mapping->area.y2 = height - mapping->area.y1;
2218                 field_mapping->data = ev_field;
2219                 ev_field->page = EV_PAGE (g_object_ref (page));
2220
2221                 g_object_set_data_full (G_OBJECT (ev_field),
2222                                         "poppler-field",
2223                                         g_object_ref (mapping->field),
2224                                         (GDestroyNotify) g_object_unref);
2225                 
2226                 retval = g_list_prepend (retval, field_mapping);
2227         }
2228         
2229         poppler_page_free_form_field_mapping (fields);
2230
2231         return g_list_reverse (retval);
2232 }
2233
2234 static gchar *
2235 pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
2236                                              EvFormField     *field)
2237         
2238 {
2239         PopplerFormField *poppler_field;
2240         gchar *text;
2241
2242         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2243         if (!poppler_field)
2244                 return NULL;
2245         
2246         text = poppler_form_field_text_get_text (poppler_field);
2247
2248         return text;
2249 }
2250
2251 static void
2252 pdf_document_forms_form_field_text_set_text (EvDocumentForms *document, 
2253                                              EvFormField     *field,
2254                                              const gchar     *text)
2255 {
2256         PopplerFormField *poppler_field;
2257
2258         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2259         if (!poppler_field)
2260                 return;
2261         
2262         poppler_form_field_text_set_text (poppler_field, text);
2263         PDF_DOCUMENT (document)->modified = TRUE;
2264 }
2265
2266 static void
2267 pdf_document_forms_form_field_button_set_state (EvDocumentForms *document, 
2268                                                 EvFormField     *field,
2269                                                 gboolean         state)
2270 {
2271         PopplerFormField *poppler_field;
2272
2273         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2274         if (!poppler_field)
2275                 return;
2276         
2277         poppler_form_field_button_set_state (poppler_field, state);
2278         PDF_DOCUMENT (document)->modified = TRUE;
2279 }
2280
2281 static gboolean
2282 pdf_document_forms_form_field_button_get_state (EvDocumentForms *document, 
2283                                                 EvFormField     *field)
2284 {
2285         PopplerFormField *poppler_field;
2286         gboolean state;
2287
2288         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2289         if (!poppler_field)
2290                 return FALSE;
2291
2292         state = poppler_form_field_button_get_state (poppler_field);
2293
2294         return state;
2295 }
2296
2297 static gchar *
2298 pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document, 
2299                                                EvFormField     *field,
2300                                                gint             index)
2301 {
2302         PopplerFormField *poppler_field;
2303         gchar *text;
2304
2305         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2306         if (!poppler_field)
2307                 return NULL;
2308
2309         text = poppler_form_field_choice_get_item (poppler_field, index);
2310
2311         return text;
2312 }
2313
2314 static int
2315 pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document, 
2316                                                   EvFormField     *field)
2317 {
2318         PopplerFormField *poppler_field;
2319         gint n_items;
2320
2321         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2322         if (!poppler_field)
2323                 return -1;
2324         
2325         n_items = poppler_form_field_choice_get_n_items (poppler_field);
2326
2327         return n_items;
2328 }
2329
2330 static gboolean
2331 pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document, 
2332                                                        EvFormField     *field,
2333                                                        gint             index)
2334 {
2335         PopplerFormField *poppler_field;
2336         gboolean selected;
2337
2338         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2339         if (!poppler_field)
2340                 return FALSE;
2341
2342         selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
2343
2344         return selected;
2345 }
2346
2347 static void
2348 pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document, 
2349                                                   EvFormField     *field,
2350                                                   gint             index)
2351 {
2352         PopplerFormField *poppler_field;
2353
2354         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2355         if (!poppler_field)
2356                 return;
2357
2358         poppler_form_field_choice_select_item (poppler_field, index);
2359         PDF_DOCUMENT (document)->modified = TRUE;
2360 }
2361
2362 static void
2363 pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document, 
2364                                                   EvFormField     *field,
2365                                                   gint             index)
2366 {
2367         PopplerFormField *poppler_field;
2368
2369         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2370         if (!poppler_field)
2371                 return;
2372
2373         poppler_form_field_choice_toggle_item (poppler_field, index);
2374         PDF_DOCUMENT (document)->modified = TRUE;
2375 }
2376
2377 static void
2378 pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document, 
2379                                                    EvFormField     *field)
2380 {
2381         PopplerFormField *poppler_field;
2382
2383         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2384         if (!poppler_field)
2385                 return;
2386         
2387         poppler_form_field_choice_unselect_all (poppler_field);
2388         PDF_DOCUMENT (document)->modified = TRUE;
2389 }
2390
2391 static void
2392 pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
2393                                                EvFormField     *field,
2394                                                const gchar     *text)
2395 {
2396         PopplerFormField *poppler_field;
2397
2398         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2399         if (!poppler_field)
2400                 return;
2401         
2402         poppler_form_field_choice_set_text (poppler_field, text);
2403         PDF_DOCUMENT (document)->modified = TRUE;
2404 }
2405
2406 static gchar *
2407 pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
2408                                                EvFormField     *field)
2409 {
2410         PopplerFormField *poppler_field;
2411         gchar *text;
2412
2413         poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2414         if (!poppler_field)
2415                 return NULL;
2416
2417         text = poppler_form_field_choice_get_text (poppler_field);
2418
2419         return text;
2420 }
2421
2422 static void
2423 pdf_document_document_forms_iface_init (EvDocumentFormsInterface *iface)
2424 {
2425         iface->get_form_fields = pdf_document_forms_get_form_fields;
2426         iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text;
2427         iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text;
2428         iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state;
2429         iface->form_field_button_get_state = pdf_document_forms_form_field_button_get_state;
2430         iface->form_field_choice_get_item = pdf_document_forms_form_field_choice_get_item;
2431         iface->form_field_choice_get_n_items = pdf_document_forms_form_field_choice_get_n_items;
2432         iface->form_field_choice_is_item_selected = pdf_document_forms_form_field_choice_is_item_selected;
2433         iface->form_field_choice_select_item = pdf_document_forms_form_field_choice_select_item;
2434         iface->form_field_choice_toggle_item = pdf_document_forms_form_field_choice_toggle_item;
2435         iface->form_field_choice_unselect_all = pdf_document_forms_form_field_choice_unselect_all;
2436         iface->form_field_choice_set_text = pdf_document_forms_form_field_choice_set_text;
2437         iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text;
2438 }
2439
2440 /* Annotations */
2441 static void
2442 poppler_annot_color_to_gdk_color (PopplerAnnot *poppler_annot,
2443                                   GdkColor     *color)
2444 {
2445         PopplerColor *poppler_color;
2446
2447         poppler_color = poppler_annot_get_color (poppler_annot);
2448         if (poppler_color) {
2449                 color->red = poppler_color->red;
2450                 color->green = poppler_color->green;
2451                 color->blue = poppler_color->blue;
2452
2453                 g_free (poppler_color);
2454         } /* TODO: else use a default color */
2455 }
2456
2457 static EvAnnotation *
2458 ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot,
2459                              EvPage       *page)
2460 {
2461         EvAnnotation *ev_annot = NULL;
2462         const gchar  *unimplemented_annot = NULL;
2463
2464         switch (poppler_annot_get_annot_type (poppler_annot)) {
2465                 case POPPLER_ANNOT_TEXT: {
2466                         PopplerAnnotText *poppler_text;
2467                         EvAnnotationText *ev_annot_text;
2468
2469                         poppler_text = POPPLER_ANNOT_TEXT (poppler_annot);
2470
2471                         ev_annot = ev_annotation_text_new (page);
2472
2473                         ev_annot_text = EV_ANNOTATION_TEXT (ev_annot);
2474                         ev_annot_text->is_open = poppler_annot_text_get_is_open (poppler_text);
2475                 }
2476                         break;
2477                 case POPPLER_ANNOT_FILE_ATTACHMENT: {
2478                         PopplerAnnotFileAttachment *poppler_annot_attachment;
2479                         EvAnnotationAttachment     *ev_annot_attachment;
2480                         PopplerAttachment          *poppler_attachment;
2481                         gchar                      *data = NULL;
2482                         gsize                       size;
2483                         GError                     *error = NULL;
2484
2485                         poppler_annot_attachment = POPPLER_ANNOT_FILE_ATTACHMENT (poppler_annot);
2486                         poppler_attachment = poppler_annot_file_attachment_get_attachment (poppler_annot_attachment);
2487
2488                         if (poppler_attachment &&
2489                             attachment_save_to_buffer (poppler_attachment, &data, &size, &error)) {
2490                                 EvAttachment *ev_attachment;
2491
2492                                 ev_attachment = ev_attachment_new (poppler_attachment->name,
2493                                                                    poppler_attachment->description,
2494                                                                    poppler_attachment->mtime,
2495                                                                    poppler_attachment->ctime,
2496                                                                    size, data);
2497                                 ev_annot = ev_annotation_attachment_new (page, ev_attachment);
2498                                 g_object_unref (ev_attachment);
2499                         } else if (error) {
2500                                 g_warning ("%s", error->message);
2501                                 g_error_free (error);
2502                         }
2503
2504                         if (poppler_attachment)
2505                                 g_object_unref (poppler_attachment);
2506                 }
2507                         break;
2508                 case POPPLER_ANNOT_LINK:
2509                 case POPPLER_ANNOT_WIDGET:
2510                         /* Ignore link and widgets annots since they are already handled */
2511                         break;
2512                 default: {
2513                         GEnumValue *enum_value;
2514
2515                         enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (POPPLER_TYPE_ANNOT_TYPE),
2516                                                        poppler_annot_get_annot_type (poppler_annot));
2517                         unimplemented_annot = enum_value ? enum_value->value_name : "Unknown annotation";
2518                 }
2519         }
2520
2521         if (unimplemented_annot) {
2522                 g_warning ("Unimplemented annotation: %s, please post a "
2523                            "bug report in Evince bugzilla "
2524                            "(http://bugzilla.gnome.org) with a testcase.",
2525                            unimplemented_annot);
2526         }
2527
2528         if (ev_annot) {
2529                 ev_annot->contents = poppler_annot_get_contents (poppler_annot);
2530                 ev_annot->name = poppler_annot_get_name (poppler_annot);
2531                 ev_annot->modified = poppler_annot_get_modified (poppler_annot);
2532                 poppler_annot_color_to_gdk_color (poppler_annot, &ev_annot->color);
2533
2534                 if (POPPLER_IS_ANNOT_MARKUP (poppler_annot)) {
2535                         PopplerAnnotMarkup *markup;
2536                         gchar *label;
2537                         gdouble opacity;
2538                         PopplerRectangle poppler_rect;
2539
2540                         markup = POPPLER_ANNOT_MARKUP (poppler_annot);
2541
2542                         if (poppler_annot_markup_get_popup_rectangle (markup, &poppler_rect)) {
2543                                 EvRectangle ev_rect;
2544                                 gboolean is_open;
2545                                 gdouble height;
2546
2547                                 poppler_page_get_size (POPPLER_PAGE (page->backend_page),
2548                                                        NULL, &height);
2549                                 ev_rect.x1 = poppler_rect.x1;
2550                                 ev_rect.x2 = poppler_rect.x2;
2551                                 ev_rect.y1 = height - poppler_rect.y2;
2552                                 ev_rect.y2 = height - poppler_rect.y1;
2553
2554                                 is_open = poppler_annot_markup_get_popup_is_open (markup);
2555
2556                                 g_object_set (ev_annot,
2557                                               "rectangle", &ev_rect,
2558                                               "is_open", is_open,
2559                                               "has_popup", TRUE,
2560                                               NULL);
2561                         } else {
2562                                 /* FIXME: Use poppler_annot_markup_has_popup() when
2563                                  * new poppler is released.
2564                                  */
2565                                 g_object_set (ev_annot,
2566                                               "has_popup", FALSE,
2567                                               NULL);
2568                         }
2569
2570                         label = poppler_annot_markup_get_label (markup);
2571                         opacity = poppler_annot_markup_get_opacity (markup);
2572
2573                         g_object_set (ev_annot,
2574                                       "label", label,
2575                                       "opacity", opacity,
2576                                       NULL);
2577
2578                         g_free (label);
2579                 }
2580         }
2581
2582         return ev_annot;
2583 }
2584
2585 static GList *
2586 pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annotations,
2587                                           EvPage                *page)
2588 {
2589         GList *retval = NULL;
2590         PdfDocument *pdf_document;
2591         PopplerPage *poppler_page;
2592         GList *annots;
2593         GList *list;
2594         gdouble height;
2595         gint i = 0;
2596
2597         pdf_document = PDF_DOCUMENT (document_annotations);
2598         poppler_page = POPPLER_PAGE (page->backend_page);
2599         annots = poppler_page_get_annot_mapping (poppler_page);
2600         poppler_page_get_size (poppler_page, NULL, &height);
2601
2602         for (list = annots; list; list = list->next) {
2603                 PopplerAnnotMapping *mapping;
2604                 EvMapping *annot_mapping;
2605                 EvAnnotation        *ev_annot;
2606
2607                 mapping = (PopplerAnnotMapping *)list->data;
2608
2609                 ev_annot = ev_annot_from_poppler_annot (mapping->annot, page);
2610                 if (!ev_annot)
2611                         continue;
2612
2613                 i++;
2614
2615                 /* Make sure annot has a unique name */
2616                 if (!ev_annot->name)
2617                         ev_annot->name = g_strdup_printf ("annot-%d-%d", page->index, i);
2618
2619                 annot_mapping = g_new (EvMapping, 1);
2620                 annot_mapping->area.x1 = mapping->area.x1;
2621                 annot_mapping->area.x2 = mapping->area.x2;
2622                 annot_mapping->area.y1 = height - mapping->area.y2;
2623                 annot_mapping->area.y2 = height - mapping->area.y1;
2624                 annot_mapping->data = ev_annot;
2625
2626                 g_object_set_data_full (G_OBJECT (ev_annot),
2627                                         "poppler-annot",
2628                                         g_object_ref (mapping->annot),
2629                                         (GDestroyNotify) g_object_unref);
2630
2631                 retval = g_list_prepend (retval, annot_mapping);
2632         }
2633
2634         poppler_page_free_annot_mapping (annots);
2635
2636         return g_list_reverse (retval);
2637 }
2638
2639 static void
2640 pdf_document_annotations_annotation_set_contents (EvDocumentAnnotations *document,
2641                                                   EvAnnotation          *annot,
2642                                                   const gchar           *contents)
2643 {
2644         PopplerAnnot *poppler_annot;
2645
2646         poppler_annot = POPPLER_ANNOT (g_object_get_data (G_OBJECT (annot), "poppler-annot"));
2647         if (!poppler_annot)
2648                 return;
2649
2650         poppler_annot_set_contents (poppler_annot, contents);
2651         PDF_DOCUMENT (document)->modified = TRUE;
2652 }
2653
2654 static void
2655 pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface)
2656 {
2657         iface->get_annotations = pdf_document_annotations_get_annotations;
2658         iface->annotation_set_contents = pdf_document_annotations_annotation_set_contents;
2659 }
2660
2661 /* Attachments */
2662 struct SaveToBufferData {
2663         gchar *buffer;
2664         gsize len, max;
2665 };
2666
2667 static gboolean
2668 attachment_save_to_buffer_callback (const gchar  *buf,
2669                                     gsize         count,
2670                                     gpointer      user_data,
2671                                     GError      **error)
2672 {
2673         struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
2674         gchar *new_buffer;
2675         gsize new_max;
2676
2677         if (sdata->len + count > sdata->max) {
2678                 new_max = MAX (sdata->max * 2, sdata->len + count);
2679                 new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
2680
2681                 sdata->buffer = new_buffer;
2682                 sdata->max = new_max;
2683         }
2684
2685         memcpy (sdata->buffer + sdata->len, buf, count);
2686         sdata->len += count;
2687
2688         return TRUE;
2689 }
2690
2691 static gboolean
2692 attachment_save_to_buffer (PopplerAttachment  *attachment,
2693                            gchar             **buffer,
2694                            gsize              *buffer_size,
2695                            GError            **error)
2696 {
2697         static const gint initial_max = 1024;
2698         struct SaveToBufferData sdata;
2699
2700         *buffer = NULL;
2701         *buffer_size = 0;
2702
2703         sdata.buffer = (gchar *) g_malloc (initial_max);
2704         sdata.max = initial_max;
2705         sdata.len = 0;
2706
2707         if (! poppler_attachment_save_to_callback (attachment,
2708                                                    attachment_save_to_buffer_callback,
2709                                                    &sdata,
2710                                                    error)) {
2711                 g_free (sdata.buffer);
2712                 return FALSE;
2713         }
2714
2715         *buffer = sdata.buffer;
2716         *buffer_size = sdata.len;
2717
2718         return TRUE;
2719 }
2720
2721 static GList *
2722 pdf_document_attachments_get_attachments (EvDocumentAttachments *document)
2723 {
2724         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2725         GList *attachments;
2726         GList *list;
2727         GList *retval = NULL;
2728
2729         attachments = poppler_document_get_attachments (pdf_document->document);
2730
2731         for (list = attachments; list; list = list->next) {
2732                 PopplerAttachment *attachment;
2733                 EvAttachment *ev_attachment;
2734                 gchar *data = NULL;
2735                 gsize size;
2736                 GError *error = NULL;
2737
2738                 attachment = (PopplerAttachment *) list->data;
2739
2740                 if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
2741                         ev_attachment = ev_attachment_new (attachment->name,
2742                                                            attachment->description,
2743                                                            attachment->mtime,
2744                                                            attachment->ctime,
2745                                                            size, data);
2746
2747                         retval = g_list_prepend (retval, ev_attachment);
2748                 } else {
2749                         if (error) {
2750                                 g_warning ("%s", error->message);
2751                                 g_error_free (error);
2752
2753                                 g_free (data);
2754                         }
2755                 }
2756
2757                 g_object_unref (attachment);
2758         }
2759
2760         return g_list_reverse (retval);
2761 }
2762
2763 static gboolean
2764 pdf_document_attachments_has_attachments (EvDocumentAttachments *document)
2765 {
2766         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2767
2768         return poppler_document_has_attachments (pdf_document->document);
2769 }
2770
2771 static void
2772 pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface)
2773 {
2774         iface->has_attachments = pdf_document_attachments_has_attachments;
2775         iface->get_attachments = pdf_document_attachments_get_attachments;
2776 }
2777
2778 /* Layers */
2779 static gboolean
2780 pdf_document_layers_has_layers (EvDocumentLayers *document)
2781 {
2782         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2783         PopplerLayersIter *iter;
2784
2785         iter = poppler_layers_iter_new (pdf_document->document);
2786         if (!iter)
2787                 return FALSE;
2788         poppler_layers_iter_free (iter);
2789
2790         return TRUE;
2791 }
2792
2793 static void
2794 build_layers_tree (PdfDocument       *pdf_document,
2795                    GtkTreeModel      *model,
2796                    GtkTreeIter       *parent,
2797                    PopplerLayersIter *iter)
2798 {
2799         do {
2800                 GtkTreeIter        tree_iter;
2801                 PopplerLayersIter *child;
2802                 PopplerLayer      *layer;
2803                 EvLayer           *ev_layer = NULL;
2804                 gboolean           visible;
2805                 gchar             *markup;
2806                 gint               rb_group = 0;
2807
2808                 layer = poppler_layers_iter_get_layer (iter);
2809                 if (layer) {
2810                         markup = g_markup_escape_text (poppler_layer_get_title (layer), -1);
2811                         visible = poppler_layer_is_visible (layer);
2812                         rb_group = poppler_layer_get_radio_button_group_id (layer);
2813                         pdf_document->layers = g_list_append (pdf_document->layers,
2814                                                               g_object_ref (layer));
2815                         ev_layer = ev_layer_new (g_list_length (pdf_document->layers) - 1,
2816                                                  poppler_layer_is_parent (layer),
2817                                                  rb_group);
2818                 } else {
2819                         gchar *title;
2820
2821                         title = poppler_layers_iter_get_title (iter);
2822                         markup = g_markup_escape_text (title, -1);
2823                         g_free (title);
2824
2825                         visible = FALSE;
2826                         layer = NULL;
2827                 }
2828
2829                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
2830                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
2831                                     EV_DOCUMENT_LAYERS_COLUMN_TITLE, markup,
2832                                     EV_DOCUMENT_LAYERS_COLUMN_VISIBLE, visible,
2833                                     EV_DOCUMENT_LAYERS_COLUMN_ENABLED, TRUE, /* FIXME */
2834                                     EV_DOCUMENT_LAYERS_COLUMN_SHOWTOGGLE, (layer != NULL),
2835                                     EV_DOCUMENT_LAYERS_COLUMN_RBGROUP, rb_group,
2836                                     EV_DOCUMENT_LAYERS_COLUMN_LAYER, ev_layer,
2837                                     -1);
2838                 if (ev_layer)
2839                         g_object_unref (ev_layer);
2840                 g_free (markup);
2841
2842                 child = poppler_layers_iter_get_child (iter);
2843                 if (child)
2844                         build_layers_tree (pdf_document, model, &tree_iter, child);
2845                 poppler_layers_iter_free (child);
2846         } while (poppler_layers_iter_next (iter));
2847 }
2848
2849 static GtkTreeModel *
2850 pdf_document_layers_get_layers (EvDocumentLayers *document)
2851 {
2852         GtkTreeModel *model = NULL;
2853         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2854         PopplerLayersIter *iter;
2855
2856         iter = poppler_layers_iter_new (pdf_document->document);
2857         if (iter) {
2858                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LAYERS_N_COLUMNS,
2859                                                              G_TYPE_STRING,  /* TITLE */
2860                                                              G_TYPE_OBJECT,  /* LAYER */
2861                                                              G_TYPE_BOOLEAN, /* VISIBLE */
2862                                                              G_TYPE_BOOLEAN, /* ENABLED */
2863                                                              G_TYPE_BOOLEAN, /* SHOWTOGGLE */
2864                                                              G_TYPE_INT);    /* RBGROUP */
2865                 build_layers_tree (pdf_document, model, NULL, iter);
2866                 poppler_layers_iter_free (iter);
2867         }
2868         return model;
2869 }
2870
2871 static void
2872 pdf_document_layers_show_layer (EvDocumentLayers *document,
2873                                 EvLayer          *layer)
2874 {
2875         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2876         guint        layer_id = ev_layer_get_id (layer);
2877
2878         poppler_layer_show (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
2879 }
2880
2881 static void
2882 pdf_document_layers_hide_layer (EvDocumentLayers *document,
2883                                 EvLayer          *layer)
2884 {
2885         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2886         guint        layer_id = ev_layer_get_id (layer);
2887
2888         poppler_layer_hide (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
2889 }
2890
2891 static gboolean
2892 pdf_document_layers_layer_is_visible (EvDocumentLayers *document,
2893                                       EvLayer          *layer)
2894 {
2895         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2896         guint        layer_id = ev_layer_get_id (layer);
2897
2898         return poppler_layer_is_visible (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
2899 }
2900
2901 static void
2902 pdf_document_document_layers_iface_init (EvDocumentLayersInterface *iface)
2903 {
2904         iface->has_layers = pdf_document_layers_has_layers;
2905         iface->get_layers = pdf_document_layers_get_layers;
2906         iface->show_layer = pdf_document_layers_show_layer;
2907         iface->hide_layer = pdf_document_layers_hide_layer;
2908         iface->layer_is_visible = pdf_document_layers_layer_is_visible;
2909 }