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