]> www.fi.muni.cz Git - evince.git/blob - backend/pdf/ev-poppler.cc
[pdf] Cache annotations in the backend
[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 EvAnnotation *
2547 ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot,
2548                              EvPage       *page)
2549 {
2550         EvAnnotation *ev_annot = NULL;
2551         const gchar  *unimplemented_annot = NULL;
2552
2553         switch (poppler_annot_get_annot_type (poppler_annot)) {
2554                 case POPPLER_ANNOT_TEXT: {
2555                         PopplerAnnotText *poppler_text;
2556                         EvAnnotationText *ev_annot_text;
2557
2558                         poppler_text = POPPLER_ANNOT_TEXT (poppler_annot);
2559
2560                         ev_annot = ev_annotation_text_new (page);
2561
2562                         ev_annot_text = EV_ANNOTATION_TEXT (ev_annot);
2563                         ev_annot_text->is_open = poppler_annot_text_get_is_open (poppler_text);
2564                 }
2565                         break;
2566                 case POPPLER_ANNOT_FILE_ATTACHMENT: {
2567                         PopplerAnnotFileAttachment *poppler_annot_attachment;
2568                         EvAnnotationAttachment     *ev_annot_attachment;
2569                         PopplerAttachment          *poppler_attachment;
2570                         gchar                      *data = NULL;
2571                         gsize                       size;
2572                         GError                     *error = NULL;
2573
2574                         poppler_annot_attachment = POPPLER_ANNOT_FILE_ATTACHMENT (poppler_annot);
2575                         poppler_attachment = poppler_annot_file_attachment_get_attachment (poppler_annot_attachment);
2576
2577                         if (poppler_attachment &&
2578                             attachment_save_to_buffer (poppler_attachment, &data, &size, &error)) {
2579                                 EvAttachment *ev_attachment;
2580
2581                                 ev_attachment = ev_attachment_new (poppler_attachment->name,
2582                                                                    poppler_attachment->description,
2583                                                                    poppler_attachment->mtime,
2584                                                                    poppler_attachment->ctime,
2585                                                                    size, data);
2586                                 ev_annot = ev_annotation_attachment_new (page, ev_attachment);
2587                                 g_object_unref (ev_attachment);
2588                         } else if (error) {
2589                                 g_warning ("%s", error->message);
2590                                 g_error_free (error);
2591                         }
2592
2593                         if (poppler_attachment)
2594                                 g_object_unref (poppler_attachment);
2595                 }
2596                         break;
2597                 case POPPLER_ANNOT_LINK:
2598                 case POPPLER_ANNOT_WIDGET:
2599                         /* Ignore link and widgets annots since they are already handled */
2600                         break;
2601                 default: {
2602                         GEnumValue *enum_value;
2603
2604                         enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (POPPLER_TYPE_ANNOT_TYPE),
2605                                                        poppler_annot_get_annot_type (poppler_annot));
2606                         unimplemented_annot = enum_value ? enum_value->value_name : "Unknown annotation";
2607                 }
2608         }
2609
2610         if (unimplemented_annot) {
2611                 g_warning ("Unimplemented annotation: %s, please post a "
2612                            "bug report in Evince bugzilla "
2613                            "(http://bugzilla.gnome.org) with a testcase.",
2614                            unimplemented_annot);
2615         }
2616
2617         if (ev_annot) {
2618                 time_t utime;
2619                 gchar *modified;
2620
2621                 ev_annot->contents = poppler_annot_get_contents (poppler_annot);
2622                 ev_annot->name = poppler_annot_get_name (poppler_annot);
2623                 modified = poppler_annot_get_modified (poppler_annot);
2624                 if (poppler_date_parse (modified, &utime)) {
2625                         ev_annot->modified = ev_document_misc_format_date (utime);
2626                         g_free (modified);
2627                 } else {
2628                         ev_annot->modified = modified;
2629                 }
2630                 poppler_annot_color_to_gdk_color (poppler_annot, &ev_annot->color);
2631
2632                 if (POPPLER_IS_ANNOT_MARKUP (poppler_annot)) {
2633                         PopplerAnnotMarkup *markup;
2634                         gchar *label;
2635                         gdouble opacity;
2636                         PopplerRectangle poppler_rect;
2637
2638                         markup = POPPLER_ANNOT_MARKUP (poppler_annot);
2639
2640                         if (poppler_annot_markup_get_popup_rectangle (markup, &poppler_rect)) {
2641                                 EvRectangle ev_rect;
2642                                 gboolean is_open;
2643                                 gdouble height;
2644
2645                                 poppler_page_get_size (POPPLER_PAGE (page->backend_page),
2646                                                        NULL, &height);
2647                                 ev_rect.x1 = poppler_rect.x1;
2648                                 ev_rect.x2 = poppler_rect.x2;
2649                                 ev_rect.y1 = height - poppler_rect.y2;
2650                                 ev_rect.y2 = height - poppler_rect.y1;
2651
2652                                 is_open = poppler_annot_markup_get_popup_is_open (markup);
2653
2654                                 g_object_set (ev_annot,
2655                                               "rectangle", &ev_rect,
2656                                               "is_open", is_open,
2657                                               "has_popup", TRUE,
2658                                               NULL);
2659                         } else {
2660                                 /* FIXME: Use poppler_annot_markup_has_popup() when
2661                                  * new poppler is released.
2662                                  */
2663                                 g_object_set (ev_annot,
2664                                               "has_popup", FALSE,
2665                                               NULL);
2666                         }
2667
2668                         label = poppler_annot_markup_get_label (markup);
2669                         opacity = poppler_annot_markup_get_opacity (markup);
2670
2671                         g_object_set (ev_annot,
2672                                       "label", label,
2673                                       "opacity", opacity,
2674                                       NULL);
2675
2676                         g_free (label);
2677                 }
2678         }
2679
2680         return ev_annot;
2681 }
2682
2683 static EvMappingList *
2684 pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annotations,
2685                                           EvPage                *page)
2686 {
2687         GList *retval = NULL;
2688         PdfDocument *pdf_document;
2689         PopplerPage *poppler_page;
2690         EvMappingList *mapping_list;
2691         GList *annots;
2692         GList *list;
2693         gdouble height;
2694         gint i = 0;
2695
2696         pdf_document = PDF_DOCUMENT (document_annotations);
2697         poppler_page = POPPLER_PAGE (page->backend_page);
2698
2699         if (pdf_document->annots) {
2700                 mapping_list = (EvMappingList *)g_hash_table_lookup (pdf_document->annots,
2701                                                                      GINT_TO_POINTER (page->index));
2702                 if (mapping_list)
2703                         return ev_mapping_list_ref (mapping_list);
2704         }
2705
2706         annots = poppler_page_get_annot_mapping (poppler_page);
2707         poppler_page_get_size (poppler_page, NULL, &height);
2708
2709         for (list = annots; list; list = list->next) {
2710                 PopplerAnnotMapping *mapping;
2711                 EvMapping *annot_mapping;
2712                 EvAnnotation        *ev_annot;
2713
2714                 mapping = (PopplerAnnotMapping *)list->data;
2715
2716                 ev_annot = ev_annot_from_poppler_annot (mapping->annot, page);
2717                 if (!ev_annot)
2718                         continue;
2719
2720                 i++;
2721
2722                 /* Make sure annot has a unique name */
2723                 if (!ev_annot->name)
2724                         ev_annot->name = g_strdup_printf ("annot-%d-%d", page->index, i);
2725
2726                 annot_mapping = g_new (EvMapping, 1);
2727                 annot_mapping->area.x1 = mapping->area.x1;
2728                 annot_mapping->area.x2 = mapping->area.x2;
2729                 annot_mapping->area.y1 = height - mapping->area.y2;
2730                 annot_mapping->area.y2 = height - mapping->area.y1;
2731                 annot_mapping->data = ev_annot;
2732
2733                 g_object_set_data_full (G_OBJECT (ev_annot),
2734                                         "poppler-annot",
2735                                         g_object_ref (mapping->annot),
2736                                         (GDestroyNotify) g_object_unref);
2737
2738                 retval = g_list_prepend (retval, annot_mapping);
2739         }
2740
2741         poppler_page_free_annot_mapping (annots);
2742
2743         if (!retval)
2744                 return NULL;
2745
2746         if (!pdf_document->annots) {
2747                 pdf_document->annots = g_hash_table_new_full (g_direct_hash,
2748                                                               g_direct_equal,
2749                                                               (GDestroyNotify)NULL,
2750                                                               (GDestroyNotify)ev_mapping_list_unref);
2751         }
2752
2753         mapping_list = ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref);
2754         g_hash_table_insert (pdf_document->annots,
2755                              GINT_TO_POINTER (page->index),
2756                              ev_mapping_list_ref (mapping_list));
2757
2758         return mapping_list;
2759 }
2760
2761 static void
2762 pdf_document_annotations_annotation_set_contents (EvDocumentAnnotations *document,
2763                                                   EvAnnotation          *annot,
2764                                                   const gchar           *contents)
2765 {
2766         PopplerAnnot *poppler_annot;
2767
2768         poppler_annot = POPPLER_ANNOT (g_object_get_data (G_OBJECT (annot), "poppler-annot"));
2769         if (!poppler_annot)
2770                 return;
2771
2772         poppler_annot_set_contents (poppler_annot, contents);
2773         PDF_DOCUMENT (document)->modified = TRUE;
2774 }
2775
2776 static void
2777 pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface)
2778 {
2779         iface->get_annotations = pdf_document_annotations_get_annotations;
2780         iface->annotation_set_contents = pdf_document_annotations_annotation_set_contents;
2781 }
2782
2783 /* Attachments */
2784 struct SaveToBufferData {
2785         gchar *buffer;
2786         gsize len, max;
2787 };
2788
2789 static gboolean
2790 attachment_save_to_buffer_callback (const gchar  *buf,
2791                                     gsize         count,
2792                                     gpointer      user_data,
2793                                     GError      **error)
2794 {
2795         struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
2796         gchar *new_buffer;
2797         gsize new_max;
2798
2799         if (sdata->len + count > sdata->max) {
2800                 new_max = MAX (sdata->max * 2, sdata->len + count);
2801                 new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
2802
2803                 sdata->buffer = new_buffer;
2804                 sdata->max = new_max;
2805         }
2806
2807         memcpy (sdata->buffer + sdata->len, buf, count);
2808         sdata->len += count;
2809
2810         return TRUE;
2811 }
2812
2813 static gboolean
2814 attachment_save_to_buffer (PopplerAttachment  *attachment,
2815                            gchar             **buffer,
2816                            gsize              *buffer_size,
2817                            GError            **error)
2818 {
2819         static const gint initial_max = 1024;
2820         struct SaveToBufferData sdata;
2821
2822         *buffer = NULL;
2823         *buffer_size = 0;
2824
2825         sdata.buffer = (gchar *) g_malloc (initial_max);
2826         sdata.max = initial_max;
2827         sdata.len = 0;
2828
2829         if (! poppler_attachment_save_to_callback (attachment,
2830                                                    attachment_save_to_buffer_callback,
2831                                                    &sdata,
2832                                                    error)) {
2833                 g_free (sdata.buffer);
2834                 return FALSE;
2835         }
2836
2837         *buffer = sdata.buffer;
2838         *buffer_size = sdata.len;
2839
2840         return TRUE;
2841 }
2842
2843 static GList *
2844 pdf_document_attachments_get_attachments (EvDocumentAttachments *document)
2845 {
2846         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2847         GList *attachments;
2848         GList *list;
2849         GList *retval = NULL;
2850
2851         attachments = poppler_document_get_attachments (pdf_document->document);
2852
2853         for (list = attachments; list; list = list->next) {
2854                 PopplerAttachment *attachment;
2855                 EvAttachment *ev_attachment;
2856                 gchar *data = NULL;
2857                 gsize size;
2858                 GError *error = NULL;
2859
2860                 attachment = (PopplerAttachment *) list->data;
2861
2862                 if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
2863                         ev_attachment = ev_attachment_new (attachment->name,
2864                                                            attachment->description,
2865                                                            attachment->mtime,
2866                                                            attachment->ctime,
2867                                                            size, data);
2868
2869                         retval = g_list_prepend (retval, ev_attachment);
2870                 } else {
2871                         if (error) {
2872                                 g_warning ("%s", error->message);
2873                                 g_error_free (error);
2874
2875                                 g_free (data);
2876                         }
2877                 }
2878
2879                 g_object_unref (attachment);
2880         }
2881
2882         return g_list_reverse (retval);
2883 }
2884
2885 static gboolean
2886 pdf_document_attachments_has_attachments (EvDocumentAttachments *document)
2887 {
2888         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2889
2890         return poppler_document_has_attachments (pdf_document->document);
2891 }
2892
2893 static void
2894 pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface)
2895 {
2896         iface->has_attachments = pdf_document_attachments_has_attachments;
2897         iface->get_attachments = pdf_document_attachments_get_attachments;
2898 }
2899
2900 /* Layers */
2901 static gboolean
2902 pdf_document_layers_has_layers (EvDocumentLayers *document)
2903 {
2904         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2905         PopplerLayersIter *iter;
2906
2907         iter = poppler_layers_iter_new (pdf_document->document);
2908         if (!iter)
2909                 return FALSE;
2910         poppler_layers_iter_free (iter);
2911
2912         return TRUE;
2913 }
2914
2915 static void
2916 build_layers_tree (PdfDocument       *pdf_document,
2917                    GtkTreeModel      *model,
2918                    GtkTreeIter       *parent,
2919                    PopplerLayersIter *iter)
2920 {
2921         do {
2922                 GtkTreeIter        tree_iter;
2923                 PopplerLayersIter *child;
2924                 PopplerLayer      *layer;
2925                 EvLayer           *ev_layer = NULL;
2926                 gboolean           visible;
2927                 gchar             *markup;
2928                 gint               rb_group = 0;
2929
2930                 layer = poppler_layers_iter_get_layer (iter);
2931                 if (layer) {
2932                         markup = g_markup_escape_text (poppler_layer_get_title (layer), -1);
2933                         visible = poppler_layer_is_visible (layer);
2934                         rb_group = poppler_layer_get_radio_button_group_id (layer);
2935                         pdf_document->layers = g_list_append (pdf_document->layers,
2936                                                               g_object_ref (layer));
2937                         ev_layer = ev_layer_new (g_list_length (pdf_document->layers) - 1,
2938                                                  poppler_layer_is_parent (layer),
2939                                                  rb_group);
2940                 } else {
2941                         gchar *title;
2942
2943                         title = poppler_layers_iter_get_title (iter);
2944                         markup = g_markup_escape_text (title, -1);
2945                         g_free (title);
2946
2947                         visible = FALSE;
2948                         layer = NULL;
2949                 }
2950
2951                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
2952                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
2953                                     EV_DOCUMENT_LAYERS_COLUMN_TITLE, markup,
2954                                     EV_DOCUMENT_LAYERS_COLUMN_VISIBLE, visible,
2955                                     EV_DOCUMENT_LAYERS_COLUMN_ENABLED, TRUE, /* FIXME */
2956                                     EV_DOCUMENT_LAYERS_COLUMN_SHOWTOGGLE, (layer != NULL),
2957                                     EV_DOCUMENT_LAYERS_COLUMN_RBGROUP, rb_group,
2958                                     EV_DOCUMENT_LAYERS_COLUMN_LAYER, ev_layer,
2959                                     -1);
2960                 if (ev_layer)
2961                         g_object_unref (ev_layer);
2962                 g_free (markup);
2963
2964                 child = poppler_layers_iter_get_child (iter);
2965                 if (child)
2966                         build_layers_tree (pdf_document, model, &tree_iter, child);
2967                 poppler_layers_iter_free (child);
2968         } while (poppler_layers_iter_next (iter));
2969 }
2970
2971 static GtkTreeModel *
2972 pdf_document_layers_get_layers (EvDocumentLayers *document)
2973 {
2974         GtkTreeModel *model = NULL;
2975         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2976         PopplerLayersIter *iter;
2977
2978         iter = poppler_layers_iter_new (pdf_document->document);
2979         if (iter) {
2980                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LAYERS_N_COLUMNS,
2981                                                              G_TYPE_STRING,  /* TITLE */
2982                                                              G_TYPE_OBJECT,  /* LAYER */
2983                                                              G_TYPE_BOOLEAN, /* VISIBLE */
2984                                                              G_TYPE_BOOLEAN, /* ENABLED */
2985                                                              G_TYPE_BOOLEAN, /* SHOWTOGGLE */
2986                                                              G_TYPE_INT);    /* RBGROUP */
2987                 build_layers_tree (pdf_document, model, NULL, iter);
2988                 poppler_layers_iter_free (iter);
2989         }
2990         return model;
2991 }
2992
2993 static void
2994 pdf_document_layers_show_layer (EvDocumentLayers *document,
2995                                 EvLayer          *layer)
2996 {
2997         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2998         guint        layer_id = ev_layer_get_id (layer);
2999
3000         poppler_layer_show (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
3001 }
3002
3003 static void
3004 pdf_document_layers_hide_layer (EvDocumentLayers *document,
3005                                 EvLayer          *layer)
3006 {
3007         PdfDocument *pdf_document = PDF_DOCUMENT (document);
3008         guint        layer_id = ev_layer_get_id (layer);
3009
3010         poppler_layer_hide (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
3011 }
3012
3013 static gboolean
3014 pdf_document_layers_layer_is_visible (EvDocumentLayers *document,
3015                                       EvLayer          *layer)
3016 {
3017         PdfDocument *pdf_document = PDF_DOCUMENT (document);
3018         guint        layer_id = ev_layer_get_id (layer);
3019
3020         return poppler_layer_is_visible (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id)));
3021 }
3022
3023 static void
3024 pdf_document_document_layers_iface_init (EvDocumentLayersInterface *iface)
3025 {
3026         iface->has_layers = pdf_document_layers_has_layers;
3027         iface->get_layers = pdf_document_layers_get_layers;
3028         iface->show_layer = pdf_document_layers_show_layer;
3029         iface->hide_layer = pdf_document_layers_hide_layer;
3030         iface->layer_is_visible = pdf_document_layers_layer_is_visible;
3031 }