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