]> www.fi.muni.cz Git - evince.git/blob - backend/pdf/ev-poppler.cc
Add support for double and triple click selections.
[evince.git] / backend / pdf / ev-poppler.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* pdfdocument.h: Implementation of EvDocument for PDF
3  * Copyright (C) 2004, Red Hat, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #ifdef HAVE_POPPLER_FORM_FIELD_BUTTON_GET_BUTTON_TYPE
23 #define HAVE_FORMS
24 #endif
25
26 #include <math.h>
27 #include <string.h>
28 #include <gtk/gtk.h>
29 #include <poppler.h>
30 #include <poppler-document.h>
31 #include <poppler-page.h>
32 #ifdef HAVE_CAIRO_PDF
33 #include <cairo-pdf.h>
34 #endif
35 #ifdef HAVE_CAIRO_PS
36 #include <cairo-ps.h>
37 #endif
38 #include <glib/gi18n.h>
39
40 #include "ev-poppler.h"
41 #include "ev-file-exporter.h"
42 #include "ev-document-find.h"
43 #include "ev-document-misc.h"
44 #include "ev-document-links.h"
45 #include "ev-document-images.h"
46 #include "ev-document-fonts.h"
47 #include "ev-document-security.h"
48 #include "ev-document-thumbnails.h"
49 #include "ev-document-transition.h"
50 #include "ev-document-forms.h"
51 #include "ev-selection.h"
52 #include "ev-attachment.h"
53 #include "ev-image.h"
54
55 #if defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS)
56 #define HAVE_CAIRO_PRINT
57 #endif
58
59 typedef struct {
60         PdfDocument *document;
61         char *text;
62         GList **pages;
63         guint idle;
64         int start_page;
65         int search_page;
66 } PdfDocumentSearch;
67
68 typedef struct {
69         EvFileExporterFormat format;
70
71         gboolean landscape;
72         
73         /* Pages per sheet */
74         gint pages_per_sheet;
75         gint pages_printed;
76         gint pages_x;
77         gint pages_y;
78         gdouble page_width;
79         gdouble page_height;
80         
81 #ifdef HAVE_CAIRO_PRINT
82         cairo_t *cr;
83 #else
84         PopplerPSFile *ps_file;
85 #endif
86 } PdfPrintContext;
87
88 struct _PdfDocumentClass
89 {
90         GObjectClass parent_class;
91 };
92
93 struct _PdfDocument
94 {
95         GObject parent_instance;
96
97         PopplerDocument *document;
98         gchar *password;
99
100         PopplerFontInfo *font_info;
101         PopplerFontsIter *fonts_iter;
102         int fonts_scanned_pages;
103
104         PdfDocumentSearch *search;
105         PdfPrintContext *print_ctx;
106 };
107
108 static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
109 static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
110 static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
111 static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
112 static void pdf_document_document_images_iface_init     (EvDocumentImagesIface     *iface);
113 static void pdf_document_document_forms_iface_init      (EvDocumentFormsIface      *iface);
114 static void pdf_document_document_fonts_iface_init      (EvDocumentFontsIface      *iface);
115 static void pdf_document_find_iface_init                (EvDocumentFindIface       *iface);
116 static void pdf_document_file_exporter_iface_init       (EvFileExporterIface       *iface);
117 static void pdf_selection_iface_init                    (EvSelectionIface          *iface);
118 static void pdf_document_page_transition_iface_init     (EvDocumentTransitionIface *iface);
119 static void pdf_document_thumbnails_get_dimensions      (EvDocumentThumbnails      *document_thumbnails,
120                                                          EvRenderContext           *rc,
121                                                          gint                      *width,
122                                                          gint                      *height);
123 static int  pdf_document_get_n_pages                    (EvDocument                *document);
124
125 static EvLinkDest *ev_link_dest_from_dest   (PdfDocument       *pdf_document,
126                                              PopplerDest       *dest);
127 static EvLink     *ev_link_from_action      (PdfDocument       *pdf_document,
128                                              PopplerAction     *action);
129 static void        pdf_document_search_free (PdfDocumentSearch *search);
130 static void        pdf_print_context_free   (PdfPrintContext   *ctx);
131
132 #ifdef HAVE_FORMS
133 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
134                          {
135                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
136                                                         pdf_document_document_iface_init);
137                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
138                                                         pdf_document_security_iface_init);
139                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
140                                                         pdf_document_document_thumbnails_iface_init);
141                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
142                                                         pdf_document_document_links_iface_init);
143                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
144                                                         pdf_document_document_images_iface_init);
145                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
146                                                         pdf_document_document_forms_iface_init);
147                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
148                                                         pdf_document_document_fonts_iface_init);
149                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
150                                                         pdf_document_find_iface_init);
151                                  G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
152                                                         pdf_document_file_exporter_iface_init);
153                                  G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
154                                                         pdf_selection_iface_init);
155                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
156                                                         pdf_document_page_transition_iface_init);
157                          });
158 #else /* !HAVE_FORMS */
159 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
160                          {
161                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
162                                                         pdf_document_document_iface_init);
163                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
164                                                         pdf_document_security_iface_init);
165                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
166                                                         pdf_document_document_thumbnails_iface_init);
167                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
168                                                         pdf_document_document_links_iface_init);
169                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
170                                                         pdf_document_document_images_iface_init);
171                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
172                                                         pdf_document_document_fonts_iface_init);
173                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
174                                                         pdf_document_find_iface_init);
175                                  G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
176                                                         pdf_document_file_exporter_iface_init);
177                                  G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
178                                                         pdf_selection_iface_init);
179                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
180                                                         pdf_document_page_transition_iface_init);
181                          });
182 #endif /* HAVE_FORMS */
183
184 static void
185 set_rc_data (PdfDocument     *pdf_document,
186              EvRenderContext *rc)
187 {
188         if (rc->data == NULL) {
189                 rc->data = poppler_document_get_page (pdf_document->document,
190                                                       rc->page);
191                 rc->destroy = g_object_unref;
192         } else {
193                 g_assert (rc->page == poppler_page_get_index (POPPLER_PAGE (rc->data)));
194         }
195 }
196
197 static void
198 pdf_document_search_free (PdfDocumentSearch   *search)
199 {
200         PdfDocument *pdf_document = search->document;
201         int n_pages;
202         int i;
203
204         if (search->idle != 0)
205                 g_source_remove (search->idle);
206
207         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
208         for (i = 0; i < n_pages; i++) {
209                 g_list_foreach (search->pages[i], (GFunc) g_free, NULL);
210                 g_list_free (search->pages[i]);
211         }
212         g_free (search->pages);
213         
214         g_free (search->text);
215         g_free (search);
216 }
217
218 static void
219 pdf_document_dispose (GObject *object)
220 {
221         PdfDocument *pdf_document = PDF_DOCUMENT(object);
222
223         if (pdf_document->print_ctx) {
224                 pdf_print_context_free (pdf_document->print_ctx);
225                 pdf_document->print_ctx = NULL;
226         }
227         
228         if (pdf_document->search) {
229                 pdf_document_search_free (pdf_document->search);
230                 pdf_document->search = NULL;
231         }
232
233         if (pdf_document->document) {
234                 g_object_unref (pdf_document->document);
235         }
236
237         if (pdf_document->font_info) { 
238                 poppler_font_info_free (pdf_document->font_info);
239         }
240
241         if (pdf_document->fonts_iter) {
242                 poppler_fonts_iter_free (pdf_document->fonts_iter);
243         }
244
245         G_OBJECT_CLASS (pdf_document_parent_class)->dispose (object);
246 }
247
248 static void
249 pdf_document_class_init (PdfDocumentClass *klass)
250 {
251         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
252
253         g_object_class->dispose = pdf_document_dispose;
254 }
255
256 static void
257 pdf_document_init (PdfDocument *pdf_document)
258 {
259         pdf_document->password = NULL;
260 }
261
262 static void
263 convert_error (GError  *poppler_error,
264                GError **error)
265 {
266         if (poppler_error == NULL)
267                 return;
268
269         if (poppler_error->domain == POPPLER_ERROR) {
270                 /* convert poppler errors into EvDocument errors */
271                 gint code = EV_DOCUMENT_ERROR_INVALID;
272                 if (poppler_error->code == POPPLER_ERROR_INVALID)
273                         code = EV_DOCUMENT_ERROR_INVALID;
274                 else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED)
275                         code = EV_DOCUMENT_ERROR_ENCRYPTED;
276                         
277
278                 g_set_error (error,
279                              EV_DOCUMENT_ERROR,
280                              code,
281                              poppler_error->message,
282                              NULL);
283         } else {
284                 g_propagate_error (error, poppler_error);
285         }
286 }
287
288
289 /* EvDocument */
290 static gboolean
291 pdf_document_save (EvDocument  *document,
292                    const char  *uri,
293                    GError     **error)
294 {
295         gboolean retval;
296         GError *poppler_error = NULL;
297
298         retval = poppler_document_save (PDF_DOCUMENT (document)->document,
299                                         uri,
300                                         &poppler_error);
301         if (! retval)
302                 convert_error (poppler_error, error);
303
304         return retval;
305 }
306
307 static gboolean
308 pdf_document_load (EvDocument   *document,
309                    const char   *uri,
310                    GError      **error)
311 {
312         GError *poppler_error = NULL;
313         PdfDocument *pdf_document = PDF_DOCUMENT (document);
314
315         pdf_document->document =
316                 poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
317
318         if (pdf_document->document == NULL) {
319                 convert_error (poppler_error, error);
320                 return FALSE;
321         }
322
323         return TRUE;
324 }
325
326 static int
327 pdf_document_get_n_pages (EvDocument *document)
328 {
329         return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
330 }
331
332 static void
333 pdf_document_get_page_size (EvDocument   *document,
334                             int           page,
335                             double       *width,
336                             double       *height)
337 {
338         PdfDocument *pdf_document = PDF_DOCUMENT (document);
339         PopplerPage *poppler_page;
340
341         poppler_page = poppler_document_get_page (pdf_document->document, page);
342         poppler_page_get_size (poppler_page, width, height);
343         g_object_unref (poppler_page);
344 }
345
346 static char *
347 pdf_document_get_page_label (EvDocument *document,
348                              int         page)
349 {
350         PopplerPage *poppler_page;
351         char *label = NULL;
352
353         poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document,
354                                                   page);
355
356         g_object_get (G_OBJECT (poppler_page),
357                       "label", &label,
358                       NULL);
359         g_object_unref (poppler_page);
360
361         return label;
362 }
363
364 static gboolean
365 pdf_document_has_attachments (EvDocument *document)
366 {
367         PdfDocument *pdf_document;
368
369         pdf_document = PDF_DOCUMENT (document);
370
371         return poppler_document_has_attachments (pdf_document->document);
372 }
373
374 struct SaveToBufferData {
375         gchar *buffer;
376         gsize len, max;
377 };
378
379 static gboolean
380 attachment_save_to_buffer_callback (const gchar  *buf,
381                                     gsize         count,
382                                     gpointer      user_data,
383                                     GError      **error)
384 {
385         struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
386         gchar *new_buffer;
387         gsize new_max;
388
389         if (sdata->len + count > sdata->max) {
390                 new_max = MAX (sdata->max * 2, sdata->len + count);
391                 new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
392
393                 sdata->buffer = new_buffer;
394                 sdata->max = new_max;
395         }
396         
397         memcpy (sdata->buffer + sdata->len, buf, count);
398         sdata->len += count;
399         
400         return TRUE;
401 }
402
403 static gboolean
404 attachment_save_to_buffer (PopplerAttachment  *attachment,
405                            gchar             **buffer,
406                            gsize              *buffer_size,
407                            GError            **error)
408 {
409         static const gint initial_max = 1024;
410         struct SaveToBufferData sdata;
411
412         *buffer = NULL;
413         *buffer_size = 0;
414
415         sdata.buffer = (gchar *) g_malloc (initial_max);
416         sdata.max = initial_max;
417         sdata.len = 0;
418
419         if (! poppler_attachment_save_to_callback (attachment,
420                                                    attachment_save_to_buffer_callback,
421                                                    &sdata,
422                                                    error)) {
423                 g_free (sdata.buffer);
424                 return FALSE;
425         }
426
427         *buffer = sdata.buffer;
428         *buffer_size = sdata.len;
429         
430         return TRUE;
431 }
432
433 static GList *
434 pdf_document_get_attachments (EvDocument *document)
435 {
436         PdfDocument *pdf_document;
437         GList *attachments;
438         GList *list;
439         GList *retval = NULL;
440
441         pdf_document = PDF_DOCUMENT (document);
442
443         if (!pdf_document_has_attachments (document))
444                 return NULL;
445
446         attachments = poppler_document_get_attachments (pdf_document->document);
447         
448         for (list = attachments; list; list = list->next) {
449                 PopplerAttachment *attachment;
450                 EvAttachment *ev_attachment;
451                 gchar *data = NULL;
452                 gsize size;
453                 GError *error = NULL;
454
455                 attachment = (PopplerAttachment *) list->data;
456
457                 if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
458                         ev_attachment = ev_attachment_new (attachment->name,
459                                                            attachment->description,
460                                                            attachment->mtime,
461                                                            attachment->ctime,
462                                                            size, data);
463                         
464                         retval = g_list_prepend (retval, ev_attachment);
465                 } else {
466                         if (error) {
467                                 g_warning ("%s", error->message);
468                                 g_error_free (error);
469
470                                 g_free (data);
471                         }
472                 }
473
474                 g_object_unref (attachment);
475         }
476
477         return g_list_reverse (retval);
478 }
479
480 static cairo_surface_t *
481 pdf_document_render (EvDocument      *document,
482                      EvRenderContext *rc)
483 {
484         PdfDocument *pdf_document;
485         cairo_surface_t *surface;
486         double width_points, height_points;
487         gint width, height;
488
489         pdf_document = PDF_DOCUMENT (document);
490
491         set_rc_data (pdf_document, rc);
492
493         poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
494
495         if (rc->rotation == 90 || rc->rotation == 270) {
496                 width = (int) ((height_points * rc->scale) + 0.5);
497                 height = (int) ((width_points * rc->scale) + 0.5);
498         } else {
499                 width = (int) ((width_points * rc->scale) + 0.5);
500                 height = (int) ((height_points * rc->scale) + 0.5);
501         }
502
503 #ifdef HAVE_POPPLER_PAGE_RENDER
504         cairo_t *cr;
505         
506         surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
507                                               width, height);
508         memset (cairo_image_surface_get_data (surface), 0xff,
509                 cairo_image_surface_get_height (surface) *
510                 cairo_image_surface_get_stride (surface));
511         
512         cr = cairo_create (surface);
513         switch (rc->rotation) {
514                 case 90:
515                         cairo_translate (cr, width, 0);
516                         break;
517                 case 180:
518                         cairo_translate (cr, width, height);
519                         break;
520                 case 270:
521                         cairo_translate (cr, 0, height);
522                         break;
523                 default:
524                         cairo_translate (cr, 0, 0);
525         }
526         cairo_scale (cr, rc->scale, rc->scale);
527         cairo_rotate (cr, rc->rotation * G_PI / 180.0);
528         poppler_page_render (POPPLER_PAGE (rc->data), cr);
529         cairo_destroy (cr);
530 #else /* HAVE_POPPLER_PAGE_RENDER */
531         GdkPixbuf *pixbuf;
532         
533         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
534                                  FALSE, 8,
535                                  width, height);
536
537         poppler_page_render_to_pixbuf (POPPLER_PAGE (rc->data),
538                                        0, 0,
539                                        width, height,
540                                        rc->scale,
541                                        rc->rotation,
542                                        pixbuf);
543         surface = ev_document_misc_surface_from_pixbuf (pixbuf);
544         g_object_unref (pixbuf);
545 #endif /* HAVE_POPPLER_PAGE_RENDER */
546
547         return surface;
548 }
549
550 /* EvDocumentSecurity */
551
552 static gboolean
553 pdf_document_has_document_security (EvDocumentSecurity *document_security)
554 {
555         /* FIXME: do we really need to have this? */
556         return FALSE;
557 }
558
559 static void
560 pdf_document_set_password (EvDocumentSecurity *document_security,
561                            const char         *password)
562 {
563         PdfDocument *document = PDF_DOCUMENT (document_security);
564
565         if (document->password)
566                 g_free (document->password);
567
568         document->password = g_strdup (password);
569 }
570
571 static EvDocumentInfo *
572 pdf_document_get_info (EvDocument *document)
573 {
574         EvDocumentInfo *info;
575         PopplerPageLayout layout;
576         PopplerPageMode mode;
577         PopplerViewerPreferences view_prefs;
578         PopplerPermissions permissions;
579
580         info = g_new0 (EvDocumentInfo, 1);
581
582         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
583                             EV_DOCUMENT_INFO_FORMAT |
584                             EV_DOCUMENT_INFO_AUTHOR |
585                             EV_DOCUMENT_INFO_SUBJECT |
586                             EV_DOCUMENT_INFO_KEYWORDS |
587                             EV_DOCUMENT_INFO_LAYOUT |
588                             EV_DOCUMENT_INFO_START_MODE |
589                             EV_DOCUMENT_INFO_PERMISSIONS |
590                             EV_DOCUMENT_INFO_UI_HINTS |
591                             EV_DOCUMENT_INFO_CREATOR |
592                             EV_DOCUMENT_INFO_PRODUCER |
593                             EV_DOCUMENT_INFO_CREATION_DATE |
594                             EV_DOCUMENT_INFO_MOD_DATE |
595                             EV_DOCUMENT_INFO_LINEARIZED |
596                             EV_DOCUMENT_INFO_N_PAGES |
597                             EV_DOCUMENT_INFO_SECURITY | 
598                             EV_DOCUMENT_INFO_PAPER_SIZE;
599
600         g_object_get (PDF_DOCUMENT (document)->document,
601                       "title", &(info->title),
602                       "format", &(info->format),
603                       "author", &(info->author),
604                       "subject", &(info->subject),
605                       "keywords", &(info->keywords),
606                       "page-mode", &mode,
607                       "page-layout", &layout,
608                       "viewer-preferences", &view_prefs,
609                       "permissions", &permissions,
610                       "creator", &(info->creator),
611                       "producer", &(info->producer),
612                       "creation-date", &(info->creation_date),
613                       "mod-date", &(info->modified_date),
614                       "linearized", &(info->linearized),
615                       NULL);
616
617         pdf_document_get_page_size(document, 0,
618                                    &(info->paper_width),
619                                    &(info->paper_height));
620
621         // Convert to mm.
622         info->paper_width = info->paper_width / 72.0f * 25.4f;
623         info->paper_height = info->paper_height / 72.0f * 25.4f;
624
625         switch (layout) {
626                 case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
627                         info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
628                         break;
629                 case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
630                         info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
631                         break;
632                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
633                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
634                         break;
635                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
636                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
637                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
638                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
639                         break;
640                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
641                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
642                         break;
643                 default:
644                         break;
645         }
646
647         switch (mode) {
648                 case POPPLER_PAGE_MODE_NONE:
649                         info->mode = EV_DOCUMENT_MODE_NONE;
650                         break;
651                 case POPPLER_PAGE_MODE_USE_THUMBS:
652                         info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
653                         break;
654                 case POPPLER_PAGE_MODE_USE_OC:
655                         info->mode = EV_DOCUMENT_MODE_USE_OC;
656                         break;
657                 case POPPLER_PAGE_MODE_FULL_SCREEN:
658                         info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
659                         break;
660                 case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
661                         info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
662                 default:
663                         break;
664         }
665
666         info->ui_hints = 0;
667         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
668                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
669         }
670         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
671                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
672         }
673         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
674                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
675         }
676         if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
677                 info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
678         }
679         if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
680                 info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
681         }
682         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
683                 info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
684         }
685         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
686                 info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
687         }
688
689         info->permissions = 0;
690         if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
691                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
692         }
693         if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
694                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
695         }
696         if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
697                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
698         }
699         if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
700                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
701         }
702
703         info->n_pages = ev_document_get_n_pages (document);
704
705         if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) {
706                 /* translators: this is the document security state */
707                 info->security = g_strdup (_("Yes"));
708         } else {
709                 /* translators: this is the document security state */
710                 info->security = g_strdup (_("No"));
711         }
712
713         return info;
714 }
715
716 static void
717 pdf_document_document_iface_init (EvDocumentIface *iface)
718 {
719         iface->save = pdf_document_save;
720         iface->load = pdf_document_load;
721         iface->get_n_pages = pdf_document_get_n_pages;
722         iface->get_page_size = pdf_document_get_page_size;
723         iface->get_page_label = pdf_document_get_page_label;
724         iface->has_attachments = pdf_document_has_attachments;
725         iface->get_attachments = pdf_document_get_attachments;
726         iface->render = pdf_document_render;
727         iface->get_info = pdf_document_get_info;
728 };
729
730 static void
731 pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
732 {
733         iface->has_document_security = pdf_document_has_document_security;
734         iface->set_password = pdf_document_set_password;
735 }
736
737 static gdouble
738 pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
739 {
740         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
741         int n_pages;
742
743         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
744
745         return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
746 }
747
748 static gboolean
749 pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
750                          int              n_pages)
751 {
752         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
753         gboolean result;
754
755         g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
756
757         if (pdf_document->font_info == NULL) { 
758                 pdf_document->font_info = poppler_font_info_new (pdf_document->document);
759         }
760
761         if (pdf_document->fonts_iter) {
762                 poppler_fonts_iter_free (pdf_document->fonts_iter);
763         }
764
765         pdf_document->fonts_scanned_pages += n_pages;
766
767         result = poppler_font_info_scan (pdf_document->font_info, n_pages,
768                                          &pdf_document->fonts_iter);
769         if (!result) {
770                 pdf_document->fonts_scanned_pages = 0;
771                 poppler_font_info_free (pdf_document->font_info);
772                 pdf_document->font_info = NULL; 
773         }
774
775         return result;
776 }
777
778 static const char *
779 font_type_to_string (PopplerFontType type)
780 {
781         switch (type) {
782                 case POPPLER_FONT_TYPE_TYPE1:
783                         return _("Type 1");
784                 case POPPLER_FONT_TYPE_TYPE1C:
785                         return _("Type 1C");
786                 case POPPLER_FONT_TYPE_TYPE3:
787                         return _("Type 3");
788                 case POPPLER_FONT_TYPE_TRUETYPE:
789                         return _("TrueType");
790                 case POPPLER_FONT_TYPE_CID_TYPE0:
791                         return _("Type 1 (CID)");
792                 case POPPLER_FONT_TYPE_CID_TYPE0C:
793                         return _("Type 1C (CID)");
794                 case POPPLER_FONT_TYPE_CID_TYPE2:
795                         return _("TrueType (CID)");
796                 default:
797                         return _("Unknown font type");
798         }
799 }
800
801 static void
802 pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
803                                GtkTreeModel    *model)
804 {
805         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
806         PopplerFontsIter *iter = pdf_document->fonts_iter;
807
808         g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
809
810         if (!iter)
811                 return;
812
813         do {
814                 GtkTreeIter list_iter;
815                 const char *name;
816                 const char *type;
817                 const char *embedded;
818                 char *details;
819                 
820                 name = poppler_fonts_iter_get_name (iter);
821
822                 if (name == NULL) {
823                         name = _("No name");
824                 }
825
826                 type = font_type_to_string (
827                         poppler_fonts_iter_get_font_type (iter));
828
829                 if (poppler_fonts_iter_is_embedded (iter)) {
830                         if (poppler_fonts_iter_is_subset (iter))
831                                 embedded = _("Embedded subset");
832                         else
833                                 embedded = _("Embedded");
834                 } else {
835                         embedded = _("Not embedded");
836                 }
837
838                 details = g_markup_printf_escaped ("%s\n%s", type, embedded);
839
840                 gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
841                 gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
842                                     EV_DOCUMENT_FONTS_COLUMN_NAME, name,
843                                     EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
844                                     -1);
845
846                 g_free (details);
847         } while (poppler_fonts_iter_next (iter));
848 }
849
850 static void
851 pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface)
852 {
853         iface->fill_model = pdf_document_fonts_fill_model;
854         iface->scan = pdf_document_fonts_scan;
855         iface->get_progress = pdf_document_fonts_get_progress;
856 }
857
858 static gboolean
859 pdf_document_links_has_document_links (EvDocumentLinks *document_links)
860 {
861         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
862         PopplerIndexIter *iter;
863
864         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
865
866         iter = poppler_index_iter_new (pdf_document->document);
867         if (iter == NULL)
868                 return FALSE;
869         poppler_index_iter_free (iter);
870
871         return TRUE;
872 }
873
874 static EvLinkDest *
875 ev_link_dest_from_dest (PdfDocument *pdf_document,
876                         PopplerDest *dest)
877 {
878         EvLinkDest *ev_dest = NULL;
879         const char *unimplemented_dest = NULL;
880
881         g_assert (dest != NULL);
882
883         switch (dest->type) {
884                 case POPPLER_DEST_XYZ: {
885                         PopplerPage *poppler_page;
886                         double height;
887
888                         poppler_page = poppler_document_get_page (pdf_document->document,
889                                                                   MAX (0, dest->page_num - 1));
890                         poppler_page_get_size (poppler_page, NULL, &height);
891                         ev_dest = ev_link_dest_new_xyz (dest->page_num - 1,
892                                                         dest->left,
893                                                         height - dest->top,
894                                                         dest->zoom);
895                         g_object_unref (poppler_page);
896                 }
897                         break;
898                 case POPPLER_DEST_FIT:
899                         ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
900                         break;
901                 case POPPLER_DEST_FITH: {
902                         PopplerPage *poppler_page;
903                         double height;
904
905                         poppler_page = poppler_document_get_page (pdf_document->document,
906                                                                   MAX (0, dest->page_num - 1));
907                         poppler_page_get_size (poppler_page, NULL, &height);
908                         ev_dest = ev_link_dest_new_fith (dest->page_num - 1,
909                                                          height - dest->top);
910                         g_object_unref (poppler_page);
911                 }
912                         break;
913                 case POPPLER_DEST_FITV:
914                         ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
915                                                          dest->left);
916                         break;
917                 case POPPLER_DEST_FITR: {
918                         PopplerPage *poppler_page;
919                         double height;
920
921                         poppler_page = poppler_document_get_page (pdf_document->document,
922                                                                   MAX (0, dest->page_num - 1));
923                         poppler_page_get_size (poppler_page, NULL, &height);
924                         ev_dest = ev_link_dest_new_fitr (dest->page_num - 1,
925                                                          dest->left,
926                                                          height - dest->bottom,
927                                                          dest->right,
928                                                          height - dest->top);
929                         g_object_unref (poppler_page);
930                 }
931                         break;
932                 case POPPLER_DEST_FITB:
933                         unimplemented_dest = "POPPLER_DEST_FITB";
934                         break;
935                 case POPPLER_DEST_FITBH:
936                         unimplemented_dest = "POPPLER_DEST_FITBH";
937                         break;
938                 case POPPLER_DEST_FITBV:
939                         unimplemented_dest = "POPPLER_DEST_FITBV";
940                         break;
941                 case POPPLER_DEST_NAMED:
942                         ev_dest = ev_link_dest_new_named (dest->named_dest);
943                         break;
944                 case POPPLER_DEST_UNKNOWN:
945                         unimplemented_dest = "POPPLER_DEST_UNKNOWN";
946                         break;
947         }
948
949         if (unimplemented_dest) {
950                 g_warning ("Unimplemented named action: %s, please post a "
951                            "bug report in Evince bugzilla "
952                            "(http://bugzilla.gnome.org) with a testcase.",
953                            unimplemented_dest);
954         }
955
956         if (!ev_dest)
957                 ev_dest = ev_link_dest_new_page (dest->page_num - 1);
958         
959         return ev_dest;
960 }
961
962 static EvLink *
963 ev_link_from_action (PdfDocument   *pdf_document,
964                      PopplerAction *action)
965 {
966         EvLink       *link = NULL;
967         EvLinkAction *ev_action = NULL;
968         const char   *unimplemented_action = NULL;
969
970         switch (action->type) {
971                 case POPPLER_ACTION_GOTO_DEST: {
972                         EvLinkDest *dest;
973                         
974                         dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest);
975                         ev_action = ev_link_action_new_dest (dest);
976                 }
977                         break;
978                 case POPPLER_ACTION_GOTO_REMOTE: {
979                         EvLinkDest *dest;
980                         
981                         dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest);
982                         ev_action = ev_link_action_new_remote (dest, 
983                                                                action->goto_remote.file_name);
984                         
985                 }
986                         break;
987                 case POPPLER_ACTION_LAUNCH:
988                         ev_action = ev_link_action_new_launch (action->launch.file_name,
989                                                                action->launch.params);
990                         break;
991                 case POPPLER_ACTION_URI:
992                         ev_action = ev_link_action_new_external_uri (action->uri.uri);
993                         break;
994                 case POPPLER_ACTION_NAMED:
995                         ev_action = ev_link_action_new_named (action->named.named_dest);
996                         break;
997                 case POPPLER_ACTION_MOVIE:
998                         unimplemented_action = "POPPLER_ACTION_MOVIE";
999                         break;
1000                 case POPPLER_ACTION_UNKNOWN:
1001                         unimplemented_action = "POPPLER_ACTION_UNKNOWN";
1002         }
1003         
1004         if (unimplemented_action) {
1005                 g_warning ("Unimplemented action: %s, please post a bug report with a testcase.",
1006                            unimplemented_action);
1007         }
1008         
1009         link = ev_link_new (action->any.title, ev_action);
1010         
1011         return link;    
1012 }
1013
1014 static void
1015 build_tree (PdfDocument      *pdf_document,
1016             GtkTreeModel     *model,
1017             GtkTreeIter      *parent,
1018             PopplerIndexIter *iter)
1019 {
1020         
1021         do {
1022                 GtkTreeIter tree_iter;
1023                 PopplerIndexIter *child;
1024                 PopplerAction *action;
1025                 EvLink *link = NULL;
1026                 gboolean expand;
1027                 char *title_markup;
1028                 
1029                 action = poppler_index_iter_get_action (iter);
1030                 expand = poppler_index_iter_is_open (iter);
1031
1032                 if (!action)
1033                         continue;
1034
1035                 switch (action->type) {
1036                         case POPPLER_ACTION_GOTO_DEST: {
1037                                 /* For bookmarks, solve named destinations */
1038                                 if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
1039                                         PopplerDest *dest;
1040                                         EvLinkDest *ev_dest = NULL;
1041                                         EvLinkAction *ev_action;
1042                                         
1043                                         dest = poppler_document_find_dest (pdf_document->document,
1044                                                                            action->goto_dest.dest->named_dest);
1045                                         if (!dest) {
1046                                                 link = ev_link_from_action (pdf_document, action);
1047                                                 break;
1048                                         }
1049                                         
1050                                         ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1051                                         poppler_dest_free (dest);
1052                                         
1053                                         ev_action = ev_link_action_new_dest (ev_dest);
1054                                         link = ev_link_new (action->any.title, ev_action);
1055                                 } else {
1056                                         link = ev_link_from_action (pdf_document, action);
1057                                 }
1058                         }
1059                                 break;
1060                         default:
1061                                 link = ev_link_from_action (pdf_document, action);
1062                                 break;
1063                 }
1064                 
1065                 if (!link) {
1066                         poppler_action_free (action);
1067                         continue;
1068                 }
1069
1070                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
1071                 title_markup = g_markup_escape_text (ev_link_get_title (link), -1);
1072                 
1073                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
1074                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
1075                                     EV_DOCUMENT_LINKS_COLUMN_LINK, link,
1076                                     EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
1077                                     -1);
1078                 
1079                 g_free (title_markup);
1080                 g_object_unref (link);
1081                 
1082                 child = poppler_index_iter_get_child (iter);
1083                 if (child)
1084                         build_tree (pdf_document, model, &tree_iter, child);
1085                 poppler_index_iter_free (child);
1086                 poppler_action_free (action);
1087                 
1088         } while (poppler_index_iter_next (iter));
1089 }
1090
1091 static GtkTreeModel *
1092 pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1093 {
1094         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1095         GtkTreeModel *model = NULL;
1096         PopplerIndexIter *iter;
1097         
1098         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1099
1100         iter = poppler_index_iter_new (pdf_document->document);
1101         /* Create the model if we have items*/
1102         if (iter != NULL) {
1103                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1104                                                              G_TYPE_STRING,
1105                                                              G_TYPE_OBJECT,
1106                                                              G_TYPE_BOOLEAN,
1107                                                              G_TYPE_STRING);
1108                 build_tree (pdf_document, model, NULL, iter);
1109                 poppler_index_iter_free (iter);
1110         }
1111         
1112         return model;
1113 }
1114
1115 static GList *
1116 pdf_document_links_get_links (EvDocumentLinks *document_links,
1117                               gint             page)
1118 {
1119         PdfDocument *pdf_document;
1120         PopplerPage *poppler_page;
1121         GList *retval = NULL;
1122         GList *mapping_list;
1123         GList *list;
1124         double height;
1125
1126         pdf_document = PDF_DOCUMENT (document_links);
1127         poppler_page = poppler_document_get_page (pdf_document->document,
1128                                                   page);
1129         mapping_list = poppler_page_get_link_mapping (poppler_page);
1130         poppler_page_get_size (poppler_page, NULL, &height);
1131
1132         for (list = mapping_list; list; list = list->next) {
1133                 PopplerLinkMapping *link_mapping;
1134                 EvLinkMapping *ev_link_mapping;
1135
1136                 link_mapping = (PopplerLinkMapping *)list->data;
1137                 ev_link_mapping = g_new (EvLinkMapping, 1);
1138                 ev_link_mapping->link = ev_link_from_action (pdf_document,
1139                                                              link_mapping->action);
1140                 ev_link_mapping->x1 = link_mapping->area.x1;
1141                 ev_link_mapping->x2 = link_mapping->area.x2;
1142                 /* Invert this for X-style coordinates */
1143                 ev_link_mapping->y1 = height - link_mapping->area.y2;
1144                 ev_link_mapping->y2 = height - link_mapping->area.y1;
1145
1146                 retval = g_list_prepend (retval, ev_link_mapping);
1147         }
1148
1149         poppler_page_free_link_mapping (mapping_list);
1150         g_object_unref (poppler_page);
1151
1152         return g_list_reverse (retval);
1153 }
1154
1155 static EvLinkDest *
1156 pdf_document_links_find_link_dest (EvDocumentLinks  *document_links,
1157                                    const gchar      *link_name)
1158 {
1159         PdfDocument *pdf_document;
1160         PopplerDest *dest;
1161         EvLinkDest *ev_dest = NULL;
1162
1163         pdf_document = PDF_DOCUMENT (document_links);
1164         dest = poppler_document_find_dest (pdf_document->document,
1165                                            link_name);
1166         if (dest) {
1167                 ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1168                 poppler_dest_free (dest);
1169         }
1170
1171         return ev_dest;
1172 }
1173
1174 static void
1175 pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
1176 {
1177         iface->has_document_links = pdf_document_links_has_document_links;
1178         iface->get_links_model = pdf_document_links_get_links_model;
1179         iface->get_links = pdf_document_links_get_links;
1180         iface->find_link_dest = pdf_document_links_find_link_dest;
1181 }
1182
1183 static GList *
1184 pdf_document_images_get_images (EvDocumentImages *document_images,
1185                                 gint              page)
1186 {
1187         GList *retval = NULL;
1188         PdfDocument *pdf_document;
1189         PopplerPage *poppler_page;
1190         GList *mapping_list;
1191         GList *list;
1192
1193         pdf_document = PDF_DOCUMENT (document_images);
1194         poppler_page = poppler_document_get_page (pdf_document->document, page);
1195         mapping_list = poppler_page_get_image_mapping (poppler_page);
1196
1197         for (list = mapping_list; list; list = list->next) {
1198                 PopplerImageMapping *image_mapping;
1199                 EvImageMapping *ev_image_mapping;
1200
1201                 image_mapping = (PopplerImageMapping *)list->data;
1202
1203                 ev_image_mapping = g_new (EvImageMapping, 1);
1204                 
1205                 ev_image_mapping->image = ev_image_new_from_pixbuf (image_mapping->image);
1206                 ev_image_mapping->x1 = image_mapping->area.x1;
1207                 ev_image_mapping->x2 = image_mapping->area.x2;
1208                 ev_image_mapping->y1 = image_mapping->area.y1;
1209                 ev_image_mapping->y2 = image_mapping->area.y2;
1210
1211                 retval = g_list_prepend (retval, ev_image_mapping);
1212         }
1213
1214         poppler_page_free_image_mapping (mapping_list);
1215         g_object_unref (poppler_page);
1216
1217         return retval;
1218 }
1219
1220 static void
1221 pdf_document_document_images_iface_init (EvDocumentImagesIface *iface)
1222 {
1223         iface->get_images = pdf_document_images_get_images;
1224 }
1225
1226 static GdkPixbuf *
1227 make_thumbnail_for_page (PdfDocument     *pdf_document,
1228                          PopplerPage     *poppler_page, 
1229                          EvRenderContext *rc)
1230 {
1231         GdkPixbuf *pixbuf;
1232         int width, height;
1233
1234         pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
1235                                                 rc, &width, &height);
1236
1237         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
1238                                  width, height);
1239         gdk_pixbuf_fill (pixbuf, 0xffffffff);
1240
1241         ev_document_fc_mutex_lock ();
1242         poppler_page_render_to_pixbuf (poppler_page, 0, 0,
1243                                        width, height,
1244                                        rc->scale, rc->rotation, pixbuf);
1245         ev_document_fc_mutex_unlock ();
1246
1247         return pixbuf;
1248 }
1249
1250 static GdkPixbuf *
1251 pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
1252                                        EvRenderContext      *rc, 
1253                                        gboolean              border)
1254 {
1255         PdfDocument *pdf_document;
1256         PopplerPage *poppler_page;
1257         GdkPixbuf *pixbuf;
1258         GdkPixbuf *border_pixbuf;
1259
1260         pdf_document = PDF_DOCUMENT (document_thumbnails);
1261
1262         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1263         g_return_val_if_fail (poppler_page != NULL, NULL);
1264
1265         pixbuf = poppler_page_get_thumbnail (poppler_page);
1266         if (pixbuf) {
1267                 /* Rotate provided thumbnail if needed */
1268                 GdkPixbuf *rotated_pixbuf;
1269
1270                 rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
1271                                                            (GdkPixbufRotation) (360 - rc->rotation));
1272                 g_object_unref (pixbuf);
1273                 pixbuf = rotated_pixbuf;
1274         } else {
1275                 /* There is no provided thumbnail.  We need to make one. */
1276                 pixbuf = make_thumbnail_for_page (pdf_document, poppler_page, rc);
1277         }
1278
1279         if (border) {           
1280                 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
1281                 g_object_unref (pixbuf);
1282                 pixbuf = border_pixbuf;
1283         }               
1284
1285         g_object_unref (poppler_page);
1286         
1287         return pixbuf;
1288 }
1289
1290 static void
1291 pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
1292                                         EvRenderContext      *rc,
1293                                         gint                 *width,
1294                                         gint                 *height)
1295 {
1296         PdfDocument *pdf_document;
1297         PopplerPage *poppler_page;
1298         gint has_thumb;
1299         
1300         pdf_document = PDF_DOCUMENT (document_thumbnails);
1301         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1302
1303         g_return_if_fail (poppler_page != NULL);
1304
1305         has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
1306
1307         if (!has_thumb) {
1308                 double page_width, page_height;
1309
1310                 poppler_page_get_size (poppler_page, &page_width, &page_height);
1311
1312                 *width = (gint) MAX (page_width * rc->scale, 1);
1313                 *height = (gint) MAX (page_height * rc->scale, 1);
1314         }
1315         
1316         if (rc->rotation == 90 || rc->rotation == 270) {
1317                 gint  temp;
1318
1319                 temp = *width;
1320                 *width = *height;
1321                 *height = temp;
1322         }
1323         
1324         g_object_unref (poppler_page);
1325 }
1326
1327 static void
1328 pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
1329 {
1330         iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
1331         iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
1332 }
1333
1334
1335 static gboolean
1336 pdf_document_search_idle_callback (void *data)
1337 {
1338         PdfDocumentSearch *search = (PdfDocumentSearch*) data;
1339         PdfDocument *pdf_document = search->document;
1340         int n_pages;
1341         GList *matches;
1342         PopplerPage *page;
1343
1344         page = poppler_document_get_page (search->document->document,
1345                                           search->search_page);
1346
1347         ev_document_doc_mutex_lock ();
1348         matches = poppler_page_find_text (page, search->text);
1349         ev_document_doc_mutex_unlock ();
1350
1351         g_object_unref (page);
1352
1353         search->pages[search->search_page] = matches;
1354         ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
1355                                   search->search_page);
1356
1357         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
1358         search->search_page += 1;
1359         if (search->search_page == n_pages) {
1360                 /* wrap around */
1361                 search->search_page = 0;
1362         }
1363
1364         if (search->search_page != search->start_page) {
1365                 return TRUE;
1366         }
1367
1368         /* We're done. */
1369         search->idle = 0; /* will return FALSE to remove */
1370         return FALSE;
1371 }
1372
1373
1374 static PdfDocumentSearch *
1375 pdf_document_search_new (PdfDocument *pdf_document,
1376                          int          start_page,
1377                          const char  *text)
1378 {
1379         PdfDocumentSearch *search;
1380         int n_pages;
1381         int i;
1382
1383         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
1384
1385         search = g_new0 (PdfDocumentSearch, 1);
1386
1387         search->text = g_strdup (text);
1388         search->pages = g_new0 (GList *, n_pages);
1389         search->document = pdf_document;
1390
1391         /* We add at low priority so the progress bar repaints */
1392         search->idle = g_idle_add_full (G_PRIORITY_LOW,
1393                                         pdf_document_search_idle_callback,
1394                                         search,
1395                                         NULL);
1396
1397         search->start_page = start_page;
1398         search->search_page = start_page;
1399
1400         return search;
1401 }
1402
1403 static void
1404 pdf_document_find_begin (EvDocumentFind   *document,
1405                          int               page,
1406                          const char       *search_string,
1407                          gboolean          case_sensitive)
1408 {
1409         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1410
1411         /* FIXME handle case_sensitive (right now XPDF
1412          * code is always case insensitive for ASCII
1413          * and case sensitive for all other languaages)
1414          */
1415
1416         if (pdf_document->search &&
1417             strcmp (search_string, pdf_document->search->text) == 0)
1418                 return;
1419
1420         if (pdf_document->search)
1421                 pdf_document_search_free (pdf_document->search);
1422
1423         pdf_document->search = pdf_document_search_new (pdf_document,
1424                                                         page,
1425                                                         search_string);
1426 }
1427
1428 static int
1429 pdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
1430 {
1431         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1432
1433         if (search) {
1434                 return g_list_length (search->pages[page]);
1435         } else {
1436                 return 0;
1437         }
1438 }
1439
1440 static gboolean
1441 pdf_document_find_get_result (EvDocumentFind *document_find,
1442                               int             page,
1443                               int             n_result,
1444                               EvRectangle    *rectangle)
1445 {
1446         PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
1447         PdfDocumentSearch *search = pdf_document->search;
1448         PopplerPage *poppler_page;
1449         PopplerRectangle *r;
1450         double height;
1451
1452         if (search == NULL)
1453                 return FALSE;
1454
1455         r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
1456                                                   n_result);
1457         if (r == NULL)
1458                 return FALSE;
1459
1460         poppler_page = poppler_document_get_page (pdf_document->document, page);
1461         poppler_page_get_size (poppler_page, NULL, &height);
1462         rectangle->x1 = r->x1;
1463         rectangle->y1 = height - r->y2;
1464         rectangle->x2 = r->x2;
1465         rectangle->y2 = height - r->y1;
1466         g_object_unref (poppler_page);
1467                 
1468         return TRUE;
1469 }
1470
1471 static int
1472 pdf_document_find_page_has_results (EvDocumentFind *document_find,
1473                                     int             page)
1474 {
1475         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1476
1477         return search && search->pages[page] != NULL;
1478 }
1479
1480 static double
1481 pdf_document_find_get_progress (EvDocumentFind *document_find)
1482 {
1483         PdfDocumentSearch *search;
1484         int n_pages, pages_done;
1485
1486         search = PDF_DOCUMENT (document_find)->search;
1487
1488         if (search == NULL) {
1489                 return 0;
1490         }
1491
1492         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
1493         if (search->search_page > search->start_page) {
1494                 pages_done = search->search_page - search->start_page + 1;
1495         } else if (search->search_page == search->start_page) {
1496                 pages_done = n_pages;
1497         } else {
1498                 pages_done = n_pages - search->start_page + search->search_page;
1499         }
1500
1501         return pages_done / (double) n_pages;
1502 }
1503
1504 static void
1505 pdf_document_find_cancel (EvDocumentFind *document)
1506 {
1507         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1508
1509         if (pdf_document->search) {
1510                 pdf_document_search_free (pdf_document->search);
1511                 pdf_document->search = NULL;
1512         }
1513 }
1514
1515 static void
1516 pdf_document_find_iface_init (EvDocumentFindIface *iface)
1517 {
1518         iface->begin = pdf_document_find_begin;
1519         iface->get_n_results = pdf_document_find_get_n_results;
1520         iface->get_result = pdf_document_find_get_result;
1521         iface->page_has_results = pdf_document_find_page_has_results;
1522         iface->get_progress = pdf_document_find_get_progress;
1523         iface->cancel = pdf_document_find_cancel;
1524 }
1525
1526 static void
1527 pdf_print_context_free (PdfPrintContext *ctx)
1528 {
1529         if (!ctx)
1530                 return;
1531
1532 #ifdef HAVE_CAIRO_PRINT
1533         if (ctx->cr) {
1534                 cairo_destroy (ctx->cr);
1535                 ctx->cr = NULL;
1536         }
1537 #else
1538         if (ctx->ps_file) {
1539                 poppler_ps_file_free (ctx->ps_file);
1540                 ctx->ps_file = NULL;
1541         }
1542 #endif
1543         g_free (ctx);
1544 }
1545
1546 static void
1547 pdf_document_file_exporter_begin (EvFileExporter        *exporter,
1548                                   EvFileExporterContext *fc)
1549 {
1550         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1551         PdfPrintContext *ctx;
1552         gdouble width, height;
1553         gboolean landscape, change_orient = FALSE;
1554 #ifdef HAVE_CAIRO_PRINT
1555         cairo_surface_t *surface = NULL;
1556 #endif
1557         
1558         if (pdf_document->print_ctx)
1559                 pdf_print_context_free (pdf_document->print_ctx);
1560         pdf_document->print_ctx = g_new0 (PdfPrintContext, 1);
1561         ctx = pdf_document->print_ctx;
1562         ctx->format = fc->format;
1563         ctx->pages_per_sheet = fc->pages_per_sheet;
1564
1565         landscape = (fc->orientation == EV_FILE_EXPORTER_LANDSCAPE);
1566         change_orient = landscape;
1567         
1568         switch (fc->pages_per_sheet) {
1569                 default:
1570                 case 1:
1571                         ctx->pages_x = 1;
1572                         ctx->pages_y = 1;
1573                         break;
1574                 case 2:
1575                         landscape = !landscape;
1576                         ctx->pages_x = 1;
1577                         ctx->pages_y = 2;
1578                         break;
1579                 case 4:
1580                         ctx->pages_x = 2;
1581                         ctx->pages_y = 2;
1582                         break;
1583                 case 6:
1584                         landscape = !landscape;
1585                         ctx->pages_x = 2;
1586                         ctx->pages_y = 3;
1587                         break;
1588                 case 9:
1589                         ctx->pages_x = 3;
1590                         ctx->pages_y = 3;
1591                         break;
1592                 case 16:
1593                         ctx->pages_x = 4;
1594                         ctx->pages_y = 4;
1595                         break;
1596         }
1597
1598         ctx->landscape = landscape;
1599
1600         if (change_orient) {
1601                 width = fc->paper_height;
1602                 height = fc->paper_width;
1603         } else {
1604                 width = fc->paper_width;
1605                 height = fc->paper_height;
1606         }
1607
1608         if (landscape) {
1609                 gint tmp;
1610
1611                 tmp = ctx->pages_x;
1612                 ctx->pages_x = ctx->pages_y;
1613                 ctx->pages_y = tmp;
1614
1615                 ctx->page_width = height / ctx->pages_x;
1616                 ctx->page_height = width / ctx->pages_y;
1617         } else {
1618                 ctx->page_width = width / ctx->pages_x;
1619                 ctx->page_height = height / ctx->pages_y;
1620         }
1621
1622         ctx->pages_printed = 0;
1623
1624         switch (fc->format) {
1625                 case EV_FILE_FORMAT_PS:
1626 #ifdef HAVE_CAIRO_PS
1627                         surface = cairo_ps_surface_create (fc->filename, width, height);
1628 #else
1629                         ctx->ps_file = poppler_ps_file_new (pdf_document->document,
1630                                                             fc->filename, fc->first_page,
1631                                                             fc->last_page - fc->first_page + 1);
1632                         poppler_ps_file_set_paper_size (ctx->ps_file, fc->paper_width, fc->paper_height);
1633                         poppler_ps_file_set_duplex (ctx->ps_file, fc->duplex);
1634 #endif /* HAVE_CAIRO_PS */
1635                         break;
1636                 case EV_FILE_FORMAT_PDF:
1637 #ifdef HAVE_CAIRO_PDF
1638                         surface = cairo_pdf_surface_create (fc->filename, width, height);
1639 #endif
1640                         break;
1641                 default:
1642                         g_assert_not_reached ();
1643         }
1644
1645 #ifdef HAVE_CAIRO_PRINT
1646         ctx->cr = cairo_create (surface);
1647         if (landscape) {
1648                 cairo_matrix_t matrix;
1649                 
1650                 cairo_translate (ctx->cr, width, 0);
1651                 cairo_matrix_init (&matrix,
1652                                    0,  1,
1653                                    -1,  0,
1654                                    0,  0);
1655                 cairo_transform (ctx->cr, &matrix);
1656         }
1657         cairo_surface_destroy (surface);
1658 #endif
1659 }
1660
1661 static void
1662 pdf_document_file_exporter_do_page (EvFileExporter  *exporter,
1663                                     EvRenderContext *rc)
1664 {
1665         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1666         PdfPrintContext *ctx = pdf_document->print_ctx;
1667         PopplerPage *poppler_page;
1668 #ifdef HAVE_CAIRO_PRINT
1669         gdouble page_width, page_height;
1670         gint    x, y;
1671 #endif
1672
1673         g_return_if_fail (pdf_document->print_ctx != NULL);
1674
1675         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1676         
1677 #ifdef HAVE_CAIRO_PRINT
1678         x = (ctx->pages_printed % ctx->pages_per_sheet) % ctx->pages_x;
1679         y = (ctx->pages_printed % ctx->pages_per_sheet) / ctx->pages_x;
1680         poppler_page_get_size (poppler_page, &page_width, &page_height);
1681         
1682         cairo_save (ctx->cr);
1683         cairo_translate (ctx->cr,
1684                          x * ctx->page_width,
1685                          y * ctx->page_height);
1686         if (ctx->landscape) {
1687                 cairo_scale (ctx->cr,
1688                              ctx->page_height / page_height,
1689                              ctx->page_height / page_height);
1690         } else {
1691                 cairo_scale (ctx->cr,
1692                              ctx->page_width / page_width,
1693                              ctx->page_height / page_height);
1694         }
1695
1696 #ifdef HAVE_POPPLER_PAGE_RENDER
1697         poppler_page_render (poppler_page, ctx->cr);
1698 #endif
1699         ctx->pages_printed++;
1700                         
1701         if (ctx->pages_printed % ctx->pages_per_sheet == 0) {
1702                 cairo_show_page (ctx->cr);
1703         }
1704         cairo_restore (ctx->cr);
1705 #else /* HAVE_CAIRO_PRINT */
1706         if (ctx->format == EV_FILE_FORMAT_PS)
1707                 poppler_page_render_to_ps (poppler_page, ctx->ps_file);
1708 #endif /* HAVE_CAIRO_PRINT */
1709         
1710         g_object_unref (poppler_page);
1711 }
1712
1713 static void
1714 pdf_document_file_exporter_end (EvFileExporter *exporter)
1715 {
1716         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1717
1718         pdf_print_context_free (pdf_document->print_ctx);
1719         pdf_document->print_ctx = NULL;
1720 }
1721
1722 static EvFileExporterCapabilities
1723 pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
1724 {
1725         return  (EvFileExporterCapabilities) (
1726                 EV_FILE_EXPORTER_CAN_PAGE_SET |
1727                 EV_FILE_EXPORTER_CAN_COPIES |
1728                 EV_FILE_EXPORTER_CAN_COLLATE |
1729                 EV_FILE_EXPORTER_CAN_REVERSE |
1730                 EV_FILE_EXPORTER_CAN_SCALE |
1731 #ifdef HAVE_CAIRO_PRINT
1732 #ifdef HAVE_POPPLER_PAGE_RENDER
1733 #if GTK_CHECK_VERSION (2, 11, 1)
1734                 EV_FILE_EXPORTER_CAN_NUMBER_UP |
1735 #endif
1736 #endif
1737 #endif
1738                 
1739 #ifdef HAVE_CAIRO_PDF
1740 #ifdef HAVE_POPPLER_PAGE_RENDER
1741                 EV_FILE_EXPORTER_CAN_GENERATE_PDF |
1742 #endif
1743 #endif
1744                 EV_FILE_EXPORTER_CAN_GENERATE_PS);
1745 }
1746
1747 static void
1748 pdf_document_file_exporter_iface_init (EvFileExporterIface *iface)
1749 {
1750         iface->begin = pdf_document_file_exporter_begin;
1751         iface->do_page = pdf_document_file_exporter_do_page;
1752         iface->end = pdf_document_file_exporter_end;
1753         iface->get_capabilities = pdf_document_file_exporter_get_capabilities;
1754 }
1755
1756 static void
1757 pdf_selection_render_selection (EvSelection      *selection,
1758                                 EvRenderContext  *rc,
1759                                 cairo_surface_t **surface,
1760                                 EvRectangle      *points,
1761                                 EvRectangle      *old_points,
1762                                 EvSelectionStyle  style,
1763                                 GdkColor         *text,
1764                                 GdkColor         *base)
1765 {
1766         PdfDocument *pdf_document;
1767         double width_points, height_points;
1768         gint width, height;
1769
1770         pdf_document = PDF_DOCUMENT (selection);
1771         set_rc_data (pdf_document, rc);
1772
1773         poppler_page_get_size (POPPLER_PAGE (rc->data),
1774                                &width_points, &height_points);
1775         width = (int) ((width_points * rc->scale) + 0.5);
1776         height = (int) ((height_points * rc->scale) + 0.5);
1777
1778 #ifdef HAVE_POPPLER_PAGE_RENDER
1779         cairo_t *cr;
1780
1781         if (*surface == NULL) {
1782                 *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1783                                                        width, height);
1784                 
1785         }
1786
1787         cr = cairo_create (*surface);
1788         cairo_scale (cr, rc->scale, rc->scale);
1789         cairo_surface_set_device_offset (*surface, 0, 0);
1790         memset (cairo_image_surface_get_data (*surface), 0x00,
1791                 cairo_image_surface_get_height (*surface) *
1792                 cairo_image_surface_get_stride (*surface));
1793         poppler_page_render_selection (POPPLER_PAGE (rc->data),
1794                                        cr,
1795                                        (PopplerRectangle *)points,
1796                                        (PopplerRectangle *)old_points,
1797                                        (PopplerSelectionStyle)style,
1798                                        text,
1799                                        base);
1800         cairo_destroy (cr);
1801 #else /* HAVE_POPPLER_PAGE_RENDER */
1802         GdkPixbuf *pixbuf;
1803         
1804         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
1805                                  TRUE, 8,
1806                                  width, height);
1807
1808         poppler_page_render_selection_to_pixbuf (POPPLER_PAGE (rc->data),
1809                                                  rc->scale, rc->rotation, pixbuf,
1810                                                  (PopplerRectangle *)points,
1811                                                  (PopplerRectangle *)old_points,
1812                                                  (PopplerSelectionStyle)style,
1813                                                  text,
1814                                                  base);
1815         if (*surface)
1816                 cairo_surface_destroy (*surface);
1817         *surface = ev_document_misc_surface_from_pixbuf (pixbuf);
1818         g_object_unref (pixbuf);
1819 #endif /* HAVE_POPPLER_PAGE_RENDER */
1820 }
1821
1822 static gchar *
1823 pdf_selection_get_selected_text (EvSelection     *selection,
1824                                  EvRenderContext *rc,
1825                                  EvSelectionStyle style,
1826                                  EvRectangle     *points)
1827 {
1828         PdfDocument *pdf_document = PDF_DOCUMENT (selection);
1829         PopplerPage *poppler_page;
1830         PopplerRectangle r;
1831         double height;
1832         char *retval;
1833         
1834         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1835         g_return_val_if_fail (poppler_page != NULL, NULL);
1836
1837         poppler_page_get_size (poppler_page, NULL, &height);
1838         r.x1 = points->x1;
1839         r.y1 = height - points->y2;
1840         r.x2 = points->x2;
1841         r.y2 = height - points->y1;
1842
1843         retval = poppler_page_get_text (poppler_page,
1844                                         (PopplerSelectionStyle)style,
1845                                         &r);
1846
1847         g_object_unref (poppler_page);
1848
1849         return retval;
1850 }
1851
1852 static GdkRegion *
1853 pdf_selection_get_selection_region (EvSelection     *selection,
1854                                     EvRenderContext *rc,
1855                                     EvSelectionStyle style,
1856                                     EvRectangle     *points)
1857 {
1858         PdfDocument *pdf_document;
1859         GdkRegion *retval;
1860
1861         pdf_document = PDF_DOCUMENT (selection);
1862
1863         set_rc_data (pdf_document, rc);
1864
1865         retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
1866                                                     rc->scale,
1867                                                     (PopplerSelectionStyle)style,
1868                                                     (PopplerRectangle *) points);
1869         return retval;
1870 }
1871
1872 static GdkRegion *
1873 pdf_selection_get_selection_map (EvSelection     *selection,
1874                                  EvRenderContext *rc)
1875 {
1876         PdfDocument *pdf_document;
1877         PopplerPage *poppler_page;
1878         PopplerRectangle points;
1879         GdkRegion *retval;
1880
1881         pdf_document = PDF_DOCUMENT (selection);
1882         poppler_page = poppler_document_get_page (pdf_document->document,
1883                                                   rc->page);
1884
1885         points.x1 = 0.0;
1886         points.y1 = 0.0;
1887         poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
1888         retval = poppler_page_get_selection_region (poppler_page, 1.0,
1889                                                     POPPLER_SELECTION_GLYPH,
1890                                                     &points);
1891         g_object_unref (poppler_page);
1892
1893         return retval;
1894 }
1895
1896 static void
1897 pdf_selection_iface_init (EvSelectionIface *iface)
1898 {
1899         iface->render_selection = pdf_selection_render_selection;
1900         iface->get_selected_text = pdf_selection_get_selected_text;
1901         iface->get_selection_region = pdf_selection_get_selection_region;
1902         iface->get_selection_map = pdf_selection_get_selection_map;
1903 }
1904
1905 /* Page Transitions */
1906 static gdouble
1907 pdf_document_get_page_duration (EvDocumentTransition *trans,
1908                                 gint                  page)
1909 {
1910         PdfDocument *pdf_document;
1911         PopplerPage *poppler_page;
1912         gdouble      duration = -1;
1913
1914         pdf_document = PDF_DOCUMENT (trans);
1915         poppler_page = poppler_document_get_page (pdf_document->document, page);
1916         if (!poppler_page)
1917                 return -1;
1918
1919         duration = poppler_page_get_duration (poppler_page);
1920         g_object_unref (poppler_page);
1921
1922         return duration;
1923 }
1924
1925 static void
1926 pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface)
1927 {
1928         iface->get_page_duration = pdf_document_get_page_duration;
1929 }
1930
1931 PdfDocument *
1932 pdf_document_new (void)
1933 {
1934         return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
1935 }
1936
1937 /* Forms */
1938 static void
1939 pdf_document_get_crop_box (EvDocument  *document, 
1940                            int          page, 
1941                            EvRectangle *rect)
1942 {
1943         PdfDocument *pdf_document;
1944         PopplerPage *poppler_page;
1945         PopplerRectangle poppler_rect;
1946
1947         pdf_document = PDF_DOCUMENT (document);
1948         poppler_page = poppler_document_get_page (pdf_document->document, page);
1949         poppler_page_get_crop_box (poppler_page, &poppler_rect);
1950         rect->x1 = poppler_rect.x1;
1951         rect->x2 = poppler_rect.x2;
1952         rect->y1 = poppler_rect.y1;
1953         rect->y2 = poppler_rect.y2;
1954 }
1955
1956 #ifdef HAVE_FORMS
1957 static EvFormField *
1958 ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
1959 {
1960         EvFormField *ev_field = NULL;
1961         gint         id;
1962         gdouble      font_size;
1963         gboolean     is_read_only;
1964
1965         id = poppler_form_field_get_id (poppler_field);
1966         font_size = poppler_form_field_get_font_size (poppler_field);
1967         is_read_only = poppler_form_field_is_read_only (poppler_field);
1968
1969         switch (poppler_form_field_get_field_type (poppler_field)) {
1970                 case POPPLER_FORM_FIELD_TEXT: {
1971                         EvFormFieldText    *field_text;
1972                         EvFormFieldTextType ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1973
1974                         switch (poppler_form_field_text_get_text_type (poppler_field)) {
1975                                 case POPPLER_FORM_TEXT_NORMAL:
1976                                         ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1977                                         break;
1978                                 case POPPLER_FORM_TEXT_MULTILINE:
1979                                         ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
1980                                         break;
1981                                 case POPPLER_FORM_TEXT_FILE_SELECT:
1982                                         ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
1983                                         break;
1984                         }
1985                         
1986                         ev_field = ev_form_field_text_new (id, ev_text_type);
1987                         field_text = EV_FORM_FIELD_TEXT (ev_field);
1988
1989                         field_text->do_spell_check = poppler_form_field_text_do_spell_check (poppler_field);
1990                         field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
1991                         field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
1992                         field_text->is_password = poppler_form_field_text_is_password (poppler_field);
1993                         
1994 #ifdef HAVE_POPPLER_FORM_FIELD_TEXT_GET_MAX_LEN
1995                         field_text->max_len = poppler_form_field_text_get_max_len (poppler_field);
1996 #endif
1997                         field_text->text = poppler_form_field_text_get_text (poppler_field);
1998
1999                 }
2000                         break;
2001                 case POPPLER_FORM_FIELD_BUTTON: {
2002                         EvFormFieldButton    *field_button;
2003                         EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2004
2005                         switch (poppler_form_field_button_get_button_type (poppler_field)) {
2006                                 case POPPLER_FORM_BUTTON_PUSH:
2007                                         ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2008                                         break;
2009                                 case POPPLER_FORM_BUTTON_CHECK:
2010                                         ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
2011                                         break;
2012                                 case POPPLER_FORM_BUTTON_RADIO:
2013                                         ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
2014                                         break;
2015                         }
2016
2017                         ev_field = ev_form_field_button_new (id, ev_button_type);
2018                         field_button = EV_FORM_FIELD_BUTTON (ev_field);
2019                         
2020                         field_button->state = poppler_form_field_button_get_state (poppler_field);
2021                 }
2022                         break;
2023                 case POPPLER_FORM_FIELD_CHOICE: {
2024                         EvFormFieldChoice    *field_choice;
2025                         EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2026
2027                         switch (poppler_form_field_choice_get_choice_type (poppler_field)) {
2028                                 case POPPLER_FORM_CHOICE_COMBO:
2029                                         ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2030                                         break;
2031                                 case EV_FORM_FIELD_CHOICE_LIST:
2032                                         ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
2033                                         break;
2034                         }
2035
2036                         ev_field = ev_form_field_choice_new (id, ev_choice_type);
2037                         field_choice = EV_FORM_FIELD_CHOICE (ev_field);
2038
2039                         field_choice->is_editable = poppler_form_field_choice_is_editable (poppler_field);
2040                         field_choice->multi_select = poppler_form_field_choice_can_select_multiple (poppler_field);
2041                         field_choice->do_spell_check = poppler_form_field_choice_do_spell_check (poppler_field);
2042                         field_choice->commit_on_sel_change = poppler_form_field_choice_commit_on_change (poppler_field);
2043
2044                         /* TODO: we need poppler_form_field_choice_get_selected_items in poppler 
2045                         field_choice->selected_items = poppler_form_field_choice_get_selected_items (poppler_field);*/
2046                         if (field_choice->is_editable)
2047                                 field_choice->text = poppler_form_field_choice_get_text (poppler_field);
2048                 }
2049                         break;
2050                 case POPPLER_FORM_FIELD_SIGNATURE:
2051                         /* TODO */
2052                         ev_field = ev_form_field_signature_new (id);
2053                         break;
2054                 case POPPLER_FORM_FIELD_UNKNOWN:
2055                         break;
2056         }
2057
2058         ev_field->font_size = font_size;
2059         ev_field->is_read_only = is_read_only;
2060
2061         return ev_field;
2062 }
2063
2064 static GList *
2065 pdf_document_forms_get_form_fields (EvDocumentForms *document, 
2066                                     gint             page)
2067 {
2068         PdfDocument *pdf_document;
2069         PopplerPage *poppler_page;
2070         GList *retval = NULL;
2071         GList *fields;
2072         GList *list;
2073         double height;
2074         
2075
2076         pdf_document = PDF_DOCUMENT (document);
2077         poppler_page = poppler_document_get_page (pdf_document->document, page);
2078         fields = poppler_page_get_form_field_mapping (poppler_page);
2079         poppler_page_get_size (poppler_page, NULL, &height);
2080
2081         for (list = fields; list; list = list->next) {
2082                 PopplerFormFieldMapping *mapping;
2083                 EvFormFieldMapping *field_mapping;
2084                 
2085                 mapping = (PopplerFormFieldMapping *)list->data;
2086
2087                 field_mapping = g_new0 (EvFormFieldMapping, 1);
2088                 field_mapping->x1 = mapping->area.x1;
2089                 field_mapping->x2 = mapping->area.x2;
2090                 field_mapping->y1 = height - mapping->area.y2;
2091                 field_mapping->y2 = height - mapping->area.y1;
2092                 field_mapping->field = ev_form_field_from_poppler_field (mapping->field);
2093                 field_mapping->field->page = page;
2094                 
2095                 retval = g_list_prepend (retval, field_mapping);
2096         }
2097         poppler_page_free_form_field_mapping (fields);
2098         g_object_unref (poppler_page);
2099
2100         return g_list_reverse (retval);
2101 }
2102
2103 static gchar *
2104 pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
2105                                              EvFormField     *field)
2106         
2107 {
2108         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2109         PopplerFormField *poppler_field;
2110         gchar *text;
2111
2112         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2113         if (!poppler_field)
2114                 return NULL;
2115         
2116         text = poppler_form_field_text_get_text (poppler_field);
2117         g_object_unref (poppler_field);
2118
2119         return text;
2120 }
2121
2122 static void
2123 pdf_document_forms_form_field_text_set_text (EvDocumentForms *document, 
2124                                              EvFormField     *field,
2125                                              const gchar     *text)
2126 {
2127         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2128         PopplerFormField *poppler_field;
2129
2130         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2131         if (!poppler_field)
2132                 return;
2133         poppler_form_field_text_set_text (poppler_field, text);
2134         g_object_unref (poppler_field);
2135 }
2136
2137 static void
2138 pdf_document_forms_form_field_button_set_state (EvDocumentForms *document, 
2139                                                 EvFormField     *field,
2140                                                 gboolean         state)
2141 {
2142         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2143         PopplerFormField *poppler_field;
2144
2145         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2146         if (!poppler_field)
2147                 return;
2148         
2149         poppler_form_field_button_set_state (poppler_field, state);
2150         g_object_unref (poppler_field);
2151 }
2152
2153 static gboolean
2154 pdf_document_forms_form_field_button_get_state (EvDocumentForms *document, 
2155                                                 EvFormField     *field)
2156 {
2157         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2158         PopplerFormField *poppler_field;
2159         gboolean state;
2160
2161         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2162         if (!poppler_field)
2163                 return FALSE;
2164
2165         state = poppler_form_field_button_get_state (poppler_field);
2166         g_object_unref (poppler_field);
2167
2168         return state;
2169 }
2170
2171 static gchar *
2172 pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document, 
2173                                                EvFormField     *field,
2174                                                gint             index)
2175 {
2176         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2177         PopplerFormField *poppler_field;
2178         gchar *text;
2179
2180         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2181         if (!poppler_field)
2182                 return NULL;
2183
2184         text = poppler_form_field_choice_get_item (poppler_field, index);
2185         g_object_unref (poppler_field);
2186
2187         return text;
2188 }
2189
2190 static int
2191 pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document, 
2192                                                   EvFormField     *field)
2193 {
2194         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2195         PopplerFormField *poppler_field;
2196         gint n_items;
2197
2198         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2199         if (!poppler_field)
2200                 return -1;
2201         
2202         n_items = poppler_form_field_choice_get_n_items (poppler_field);
2203         g_object_unref (poppler_field);
2204
2205         return n_items;
2206 }
2207
2208 static gboolean
2209 pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document, 
2210                                                        EvFormField     *field,
2211                                                        gint             index)
2212 {
2213         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2214         PopplerFormField *poppler_field;
2215         gboolean selected;
2216
2217         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2218         if (!poppler_field)
2219                 return FALSE;
2220
2221         selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
2222         g_object_unref (poppler_field);
2223
2224         return selected;
2225 }
2226
2227 static void
2228 pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document, 
2229                                                   EvFormField     *field,
2230                                                   gint             index)
2231 {
2232         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2233         PopplerFormField *poppler_field;
2234
2235         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2236         if (!poppler_field)
2237                 return;
2238
2239         poppler_form_field_choice_select_item (poppler_field, index);
2240         g_object_unref (poppler_field);
2241 }
2242
2243 static void
2244 pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document, 
2245                                                   EvFormField     *field,
2246                                                   gint             index)
2247 {
2248         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2249         PopplerFormField *poppler_field;
2250
2251         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2252         if (!poppler_field)
2253                 return;
2254
2255         poppler_form_field_choice_toggle_item (poppler_field, index);
2256         g_object_unref (poppler_field);
2257 }
2258
2259 static void
2260 pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document, 
2261                                                    EvFormField     *field)
2262 {
2263         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2264         PopplerFormField *poppler_field;
2265
2266         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2267         if (!poppler_field)
2268                 return;
2269         
2270         poppler_form_field_choice_unselect_all (poppler_field);
2271         g_object_unref (poppler_field);
2272 }
2273
2274 static void
2275 pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
2276                                                EvFormField     *field,
2277                                                const gchar     *text)
2278 {
2279         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2280         PopplerFormField *poppler_field;
2281
2282         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2283         if (!poppler_field)
2284                 return;
2285         
2286         poppler_form_field_choice_set_text (poppler_field, text);
2287         g_object_unref (poppler_field);
2288 }
2289
2290 static gchar *
2291 pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
2292                                                EvFormField     *field)
2293 {
2294         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2295         PopplerFormField *poppler_field;
2296         gchar *text;
2297
2298         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2299         if (!poppler_field)
2300                 return NULL;
2301
2302         text = poppler_form_field_choice_get_text (poppler_field);
2303         g_object_unref (poppler_field);
2304
2305         return text;
2306 }
2307
2308 static void
2309 pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface)
2310 {
2311         iface->get_form_fields = pdf_document_forms_get_form_fields;
2312         iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text;
2313         iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text;
2314         iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state;
2315         iface->form_field_button_get_state = pdf_document_forms_form_field_button_get_state;
2316         iface->form_field_choice_get_item = pdf_document_forms_form_field_choice_get_item;
2317         iface->form_field_choice_get_n_items = pdf_document_forms_form_field_choice_get_n_items;
2318         iface->form_field_choice_is_item_selected = pdf_document_forms_form_field_choice_is_item_selected;
2319         iface->form_field_choice_select_item = pdf_document_forms_form_field_choice_select_item;
2320         iface->form_field_choice_toggle_item = pdf_document_forms_form_field_choice_toggle_item;
2321         iface->form_field_choice_unselect_all = pdf_document_forms_form_field_choice_unselect_all;
2322         iface->form_field_choice_set_text = pdf_document_forms_form_field_choice_set_text;
2323         iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text;
2324 }
2325 #endif /* HAVE_FORMS */