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