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