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