]> www.fi.muni.cz Git - evince.git/blob - backend/pdf/ev-poppler.cc
Create always a portrait cairo surface and rotate when needed for
[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 gboolean
572 pdf_document_can_get_text (EvDocument *document)
573 {
574         return TRUE;
575 }
576
577 static EvDocumentInfo *
578 pdf_document_get_info (EvDocument *document)
579 {
580         EvDocumentInfo *info;
581         PopplerPageLayout layout;
582         PopplerPageMode mode;
583         PopplerViewerPreferences view_prefs;
584         PopplerPermissions permissions;
585
586         info = g_new0 (EvDocumentInfo, 1);
587
588         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
589                             EV_DOCUMENT_INFO_FORMAT |
590                             EV_DOCUMENT_INFO_AUTHOR |
591                             EV_DOCUMENT_INFO_SUBJECT |
592                             EV_DOCUMENT_INFO_KEYWORDS |
593                             EV_DOCUMENT_INFO_LAYOUT |
594                             EV_DOCUMENT_INFO_START_MODE |
595                             EV_DOCUMENT_INFO_PERMISSIONS |
596                             EV_DOCUMENT_INFO_UI_HINTS |
597                             EV_DOCUMENT_INFO_CREATOR |
598                             EV_DOCUMENT_INFO_PRODUCER |
599                             EV_DOCUMENT_INFO_CREATION_DATE |
600                             EV_DOCUMENT_INFO_MOD_DATE |
601                             EV_DOCUMENT_INFO_LINEARIZED |
602                             EV_DOCUMENT_INFO_N_PAGES |
603                             EV_DOCUMENT_INFO_SECURITY | 
604                             EV_DOCUMENT_INFO_PAPER_SIZE;
605
606         g_object_get (PDF_DOCUMENT (document)->document,
607                       "title", &(info->title),
608                       "format", &(info->format),
609                       "author", &(info->author),
610                       "subject", &(info->subject),
611                       "keywords", &(info->keywords),
612                       "page-mode", &mode,
613                       "page-layout", &layout,
614                       "viewer-preferences", &view_prefs,
615                       "permissions", &permissions,
616                       "creator", &(info->creator),
617                       "producer", &(info->producer),
618                       "creation-date", &(info->creation_date),
619                       "mod-date", &(info->modified_date),
620                       "linearized", &(info->linearized),
621                       NULL);
622
623         pdf_document_get_page_size(document, 0,
624                                    &(info->paper_width),
625                                    &(info->paper_height));
626
627         // Convert to mm.
628         info->paper_width = info->paper_width / 72.0f * 25.4f;
629         info->paper_height = info->paper_height / 72.0f * 25.4f;
630
631         switch (layout) {
632                 case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
633                         info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
634                         break;
635                 case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
636                         info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
637                         break;
638                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
639                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
640                         break;
641                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
642                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
643                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
644                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
645                         break;
646                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
647                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
648                         break;
649                 default:
650                         break;
651         }
652
653         switch (mode) {
654                 case POPPLER_PAGE_MODE_NONE:
655                         info->mode = EV_DOCUMENT_MODE_NONE;
656                         break;
657                 case POPPLER_PAGE_MODE_USE_THUMBS:
658                         info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
659                         break;
660                 case POPPLER_PAGE_MODE_USE_OC:
661                         info->mode = EV_DOCUMENT_MODE_USE_OC;
662                         break;
663                 case POPPLER_PAGE_MODE_FULL_SCREEN:
664                         info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
665                         break;
666                 case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
667                         info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
668                 default:
669                         break;
670         }
671
672         info->ui_hints = 0;
673         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
674                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
675         }
676         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
677                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
678         }
679         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
680                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
681         }
682         if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
683                 info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
684         }
685         if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
686                 info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
687         }
688         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
689                 info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
690         }
691         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
692                 info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
693         }
694
695         info->permissions = 0;
696         if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
697                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
698         }
699         if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
700                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
701         }
702         if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
703                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
704         }
705         if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
706                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
707         }
708
709         info->n_pages = ev_document_get_n_pages (document);
710
711         if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) {
712                 /* translators: this is the document security state */
713                 info->security = g_strdup (_("Yes"));
714         } else {
715                 /* translators: this is the document security state */
716                 info->security = g_strdup (_("No"));
717         }
718
719         return info;
720 }
721
722 static char *
723 pdf_document_get_text (EvDocument *document, int page, EvRectangle *rect)
724 {
725         PdfDocument *pdf_document = PDF_DOCUMENT (document);
726         PopplerPage *poppler_page;
727         PopplerRectangle r;
728         double height;
729         char *text;
730         
731         poppler_page = poppler_document_get_page (pdf_document->document, page);
732         g_return_val_if_fail (poppler_page != NULL, NULL);
733
734         poppler_page_get_size (poppler_page, NULL, &height);
735         r.x1 = rect->x1;
736         r.y1 = height - rect->y2;
737         r.x2 = rect->x2;
738         r.y2 = height - rect->y1;
739
740         text = poppler_page_get_text (poppler_page, &r);
741
742         g_object_unref (poppler_page);
743
744         return text;
745 }
746
747 static void
748 pdf_document_document_iface_init (EvDocumentIface *iface)
749 {
750         iface->save = pdf_document_save;
751         iface->load = pdf_document_load;
752         iface->get_n_pages = pdf_document_get_n_pages;
753         iface->get_page_size = pdf_document_get_page_size;
754         iface->get_page_label = pdf_document_get_page_label;
755         iface->has_attachments = pdf_document_has_attachments;
756         iface->get_attachments = pdf_document_get_attachments;
757         iface->render = pdf_document_render;
758         iface->get_text = pdf_document_get_text;
759         iface->can_get_text = pdf_document_can_get_text;
760         iface->get_info = pdf_document_get_info;
761 };
762
763 static void
764 pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
765 {
766         iface->has_document_security = pdf_document_has_document_security;
767         iface->set_password = pdf_document_set_password;
768 }
769
770 static gdouble
771 pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
772 {
773         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
774         int n_pages;
775
776         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
777
778         return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
779 }
780
781 static gboolean
782 pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
783                          int              n_pages)
784 {
785         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
786         gboolean result;
787
788         g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
789
790         if (pdf_document->font_info == NULL) { 
791                 pdf_document->font_info = poppler_font_info_new (pdf_document->document);
792         }
793
794         if (pdf_document->fonts_iter) {
795                 poppler_fonts_iter_free (pdf_document->fonts_iter);
796         }
797
798         pdf_document->fonts_scanned_pages += n_pages;
799
800         result = poppler_font_info_scan (pdf_document->font_info, n_pages,
801                                          &pdf_document->fonts_iter);
802         if (!result) {
803                 pdf_document->fonts_scanned_pages = 0;
804                 poppler_font_info_free (pdf_document->font_info);
805                 pdf_document->font_info = NULL; 
806         }
807
808         return result;
809 }
810
811 static const char *
812 font_type_to_string (PopplerFontType type)
813 {
814         switch (type) {
815                 case POPPLER_FONT_TYPE_TYPE1:
816                         return _("Type 1");
817                 case POPPLER_FONT_TYPE_TYPE1C:
818                         return _("Type 1C");
819                 case POPPLER_FONT_TYPE_TYPE3:
820                         return _("Type 3");
821                 case POPPLER_FONT_TYPE_TRUETYPE:
822                         return _("TrueType");
823                 case POPPLER_FONT_TYPE_CID_TYPE0:
824                         return _("Type 1 (CID)");
825                 case POPPLER_FONT_TYPE_CID_TYPE0C:
826                         return _("Type 1C (CID)");
827                 case POPPLER_FONT_TYPE_CID_TYPE2:
828                         return _("TrueType (CID)");
829                 default:
830                         return _("Unknown font type");
831         }
832 }
833
834 static void
835 pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
836                                GtkTreeModel    *model)
837 {
838         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
839         PopplerFontsIter *iter = pdf_document->fonts_iter;
840
841         g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
842
843         if (!iter)
844                 return;
845
846         do {
847                 GtkTreeIter list_iter;
848                 const char *name;
849                 const char *type;
850                 const char *embedded;
851                 char *details;
852                 
853                 name = poppler_fonts_iter_get_name (iter);
854
855                 if (name == NULL) {
856                         name = _("No name");
857                 }
858
859                 type = font_type_to_string (
860                         poppler_fonts_iter_get_font_type (iter));
861
862                 if (poppler_fonts_iter_is_embedded (iter)) {
863                         if (poppler_fonts_iter_is_subset (iter))
864                                 embedded = _("Embedded subset");
865                         else
866                                 embedded = _("Embedded");
867                 } else {
868                         embedded = _("Not embedded");
869                 }
870
871                 details = g_markup_printf_escaped ("%s\n%s", type, embedded);
872
873                 gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
874                 gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
875                                     EV_DOCUMENT_FONTS_COLUMN_NAME, name,
876                                     EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
877                                     -1);
878
879                 g_free (details);
880         } while (poppler_fonts_iter_next (iter));
881 }
882
883 static void
884 pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface)
885 {
886         iface->fill_model = pdf_document_fonts_fill_model;
887         iface->scan = pdf_document_fonts_scan;
888         iface->get_progress = pdf_document_fonts_get_progress;
889 }
890
891 static gboolean
892 pdf_document_links_has_document_links (EvDocumentLinks *document_links)
893 {
894         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
895         PopplerIndexIter *iter;
896
897         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
898
899         iter = poppler_index_iter_new (pdf_document->document);
900         if (iter == NULL)
901                 return FALSE;
902         poppler_index_iter_free (iter);
903
904         return TRUE;
905 }
906
907 static EvLinkDest *
908 ev_link_dest_from_dest (PdfDocument *pdf_document,
909                         PopplerDest *dest)
910 {
911         EvLinkDest *ev_dest = NULL;
912         const char *unimplemented_dest = NULL;
913
914         g_assert (dest != NULL);
915
916         switch (dest->type) {
917                 case POPPLER_DEST_XYZ: {
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_xyz (dest->page_num - 1,
925                                                         dest->left,
926                                                         height - dest->top,
927                                                         dest->zoom);
928                         g_object_unref (poppler_page);
929                 }
930                         break;
931                 case POPPLER_DEST_FIT:
932                         ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
933                         break;
934                 case POPPLER_DEST_FITH: {
935                         PopplerPage *poppler_page;
936                         double height;
937
938                         poppler_page = poppler_document_get_page (pdf_document->document,
939                                                                   MAX (0, dest->page_num - 1));
940                         poppler_page_get_size (poppler_page, NULL, &height);
941                         ev_dest = ev_link_dest_new_fith (dest->page_num - 1,
942                                                          height - dest->top);
943                         g_object_unref (poppler_page);
944                 }
945                         break;
946                 case POPPLER_DEST_FITV:
947                         ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
948                                                          dest->left);
949                         break;
950                 case POPPLER_DEST_FITR: {
951                         PopplerPage *poppler_page;
952                         double height;
953
954                         poppler_page = poppler_document_get_page (pdf_document->document,
955                                                                   MAX (0, dest->page_num - 1));
956                         poppler_page_get_size (poppler_page, NULL, &height);
957                         ev_dest = ev_link_dest_new_fitr (dest->page_num - 1,
958                                                          dest->left,
959                                                          height - dest->bottom,
960                                                          dest->right,
961                                                          height - dest->top);
962                         g_object_unref (poppler_page);
963                 }
964                         break;
965                 case POPPLER_DEST_FITB:
966                         unimplemented_dest = "POPPLER_DEST_FITB";
967                         break;
968                 case POPPLER_DEST_FITBH:
969                         unimplemented_dest = "POPPLER_DEST_FITBH";
970                         break;
971                 case POPPLER_DEST_FITBV:
972                         unimplemented_dest = "POPPLER_DEST_FITBV";
973                         break;
974                 case POPPLER_DEST_NAMED:
975                         ev_dest = ev_link_dest_new_named (dest->named_dest);
976                         break;
977                 case POPPLER_DEST_UNKNOWN:
978                         unimplemented_dest = "POPPLER_DEST_UNKNOWN";
979                         break;
980         }
981
982         if (unimplemented_dest) {
983                 g_warning ("Unimplemented named action: %s, please post a "
984                            "bug report in Evince bugzilla "
985                            "(http://bugzilla.gnome.org) with a testcase.",
986                            unimplemented_dest);
987         }
988
989         if (!ev_dest)
990                 ev_dest = ev_link_dest_new_page (dest->page_num - 1);
991         
992         return ev_dest;
993 }
994
995 static EvLink *
996 ev_link_from_action (PdfDocument   *pdf_document,
997                      PopplerAction *action)
998 {
999         EvLink       *link = NULL;
1000         EvLinkAction *ev_action = NULL;
1001         const char   *unimplemented_action = NULL;
1002
1003         switch (action->type) {
1004                 case POPPLER_ACTION_GOTO_DEST: {
1005                         EvLinkDest *dest;
1006                         
1007                         dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest);
1008                         ev_action = ev_link_action_new_dest (dest);
1009                 }
1010                         break;
1011                 case POPPLER_ACTION_GOTO_REMOTE: {
1012                         EvLinkDest *dest;
1013                         
1014                         dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest);
1015                         ev_action = ev_link_action_new_remote (dest, 
1016                                                                action->goto_remote.file_name);
1017                         
1018                 }
1019                         break;
1020                 case POPPLER_ACTION_LAUNCH:
1021                         ev_action = ev_link_action_new_launch (action->launch.file_name,
1022                                                                action->launch.params);
1023                         break;
1024                 case POPPLER_ACTION_URI:
1025                         ev_action = ev_link_action_new_external_uri (action->uri.uri);
1026                         break;
1027                 case POPPLER_ACTION_NAMED:
1028                         ev_action = ev_link_action_new_named (action->named.named_dest);
1029                         break;
1030                 case POPPLER_ACTION_MOVIE:
1031                         unimplemented_action = "POPPLER_ACTION_MOVIE";
1032                         break;
1033                 case POPPLER_ACTION_UNKNOWN:
1034                         unimplemented_action = "POPPLER_ACTION_UNKNOWN";
1035         }
1036         
1037         if (unimplemented_action) {
1038                 g_warning ("Unimplemented action: %s, please post a bug report with a testcase.",
1039                            unimplemented_action);
1040         }
1041         
1042         link = ev_link_new (action->any.title, ev_action);
1043         
1044         return link;    
1045 }
1046
1047 static void
1048 build_tree (PdfDocument      *pdf_document,
1049             GtkTreeModel     *model,
1050             GtkTreeIter      *parent,
1051             PopplerIndexIter *iter)
1052 {
1053         
1054         do {
1055                 GtkTreeIter tree_iter;
1056                 PopplerIndexIter *child;
1057                 PopplerAction *action;
1058                 EvLink *link = NULL;
1059                 gboolean expand;
1060                 char *title_markup;
1061                 
1062                 action = poppler_index_iter_get_action (iter);
1063                 expand = poppler_index_iter_is_open (iter);
1064
1065                 if (!action)
1066                         continue;
1067
1068                 switch (action->type) {
1069                         case POPPLER_ACTION_GOTO_DEST: {
1070                                 /* For bookmarks, solve named destinations */
1071                                 if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
1072                                         PopplerDest *dest;
1073                                         EvLinkDest *ev_dest = NULL;
1074                                         EvLinkAction *ev_action;
1075                                         
1076                                         dest = poppler_document_find_dest (pdf_document->document,
1077                                                                            action->goto_dest.dest->named_dest);
1078                                         if (!dest) {
1079                                                 link = ev_link_from_action (pdf_document, action);
1080                                                 break;
1081                                         }
1082                                         
1083                                         ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1084                                         poppler_dest_free (dest);
1085                                         
1086                                         ev_action = ev_link_action_new_dest (ev_dest);
1087                                         link = ev_link_new (action->any.title, ev_action);
1088                                 } else {
1089                                         link = ev_link_from_action (pdf_document, action);
1090                                 }
1091                         }
1092                                 break;
1093                         default:
1094                                 link = ev_link_from_action (pdf_document, action);
1095                                 break;
1096                 }
1097                 
1098                 if (!link) {
1099                         poppler_action_free (action);
1100                         continue;
1101                 }
1102
1103                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
1104                 title_markup = g_markup_escape_text (ev_link_get_title (link), -1);
1105                 
1106                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
1107                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
1108                                     EV_DOCUMENT_LINKS_COLUMN_LINK, link,
1109                                     EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
1110                                     -1);
1111                 
1112                 g_free (title_markup);
1113                 g_object_unref (link);
1114                 
1115                 child = poppler_index_iter_get_child (iter);
1116                 if (child)
1117                         build_tree (pdf_document, model, &tree_iter, child);
1118                 poppler_index_iter_free (child);
1119                 poppler_action_free (action);
1120                 
1121         } while (poppler_index_iter_next (iter));
1122 }
1123
1124 static GtkTreeModel *
1125 pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1126 {
1127         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1128         GtkTreeModel *model = NULL;
1129         PopplerIndexIter *iter;
1130         
1131         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1132
1133         iter = poppler_index_iter_new (pdf_document->document);
1134         /* Create the model if we have items*/
1135         if (iter != NULL) {
1136                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1137                                                              G_TYPE_STRING,
1138                                                              G_TYPE_OBJECT,
1139                                                              G_TYPE_BOOLEAN,
1140                                                              G_TYPE_STRING);
1141                 build_tree (pdf_document, model, NULL, iter);
1142                 poppler_index_iter_free (iter);
1143         }
1144         
1145         return model;
1146 }
1147
1148 static GList *
1149 pdf_document_links_get_links (EvDocumentLinks *document_links,
1150                               gint             page)
1151 {
1152         PdfDocument *pdf_document;
1153         PopplerPage *poppler_page;
1154         GList *retval = NULL;
1155         GList *mapping_list;
1156         GList *list;
1157         double height;
1158
1159         pdf_document = PDF_DOCUMENT (document_links);
1160         poppler_page = poppler_document_get_page (pdf_document->document,
1161                                                   page);
1162         mapping_list = poppler_page_get_link_mapping (poppler_page);
1163         poppler_page_get_size (poppler_page, NULL, &height);
1164
1165         for (list = mapping_list; list; list = list->next) {
1166                 PopplerLinkMapping *link_mapping;
1167                 EvLinkMapping *ev_link_mapping;
1168
1169                 link_mapping = (PopplerLinkMapping *)list->data;
1170                 ev_link_mapping = g_new (EvLinkMapping, 1);
1171                 ev_link_mapping->link = ev_link_from_action (pdf_document,
1172                                                              link_mapping->action);
1173                 ev_link_mapping->x1 = link_mapping->area.x1;
1174                 ev_link_mapping->x2 = link_mapping->area.x2;
1175                 /* Invert this for X-style coordinates */
1176                 ev_link_mapping->y1 = height - link_mapping->area.y2;
1177                 ev_link_mapping->y2 = height - link_mapping->area.y1;
1178
1179                 retval = g_list_prepend (retval, ev_link_mapping);
1180         }
1181
1182         poppler_page_free_link_mapping (mapping_list);
1183         g_object_unref (poppler_page);
1184
1185         return g_list_reverse (retval);
1186 }
1187
1188 static EvLinkDest *
1189 pdf_document_links_find_link_dest (EvDocumentLinks  *document_links,
1190                                    const gchar      *link_name)
1191 {
1192         PdfDocument *pdf_document;
1193         PopplerDest *dest;
1194         EvLinkDest *ev_dest = NULL;
1195
1196         pdf_document = PDF_DOCUMENT (document_links);
1197         dest = poppler_document_find_dest (pdf_document->document,
1198                                            link_name);
1199         if (dest) {
1200                 ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1201                 poppler_dest_free (dest);
1202         }
1203
1204         return ev_dest;
1205 }
1206
1207 static void
1208 pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
1209 {
1210         iface->has_document_links = pdf_document_links_has_document_links;
1211         iface->get_links_model = pdf_document_links_get_links_model;
1212         iface->get_links = pdf_document_links_get_links;
1213         iface->find_link_dest = pdf_document_links_find_link_dest;
1214 }
1215
1216 static GList *
1217 pdf_document_images_get_images (EvDocumentImages *document_images,
1218                                 gint              page)
1219 {
1220         GList *retval = NULL;
1221         PdfDocument *pdf_document;
1222         PopplerPage *poppler_page;
1223         GList *mapping_list;
1224         GList *list;
1225
1226         pdf_document = PDF_DOCUMENT (document_images);
1227         poppler_page = poppler_document_get_page (pdf_document->document, page);
1228         mapping_list = poppler_page_get_image_mapping (poppler_page);
1229
1230         for (list = mapping_list; list; list = list->next) {
1231                 PopplerImageMapping *image_mapping;
1232                 EvImageMapping *ev_image_mapping;
1233
1234                 image_mapping = (PopplerImageMapping *)list->data;
1235
1236                 ev_image_mapping = g_new (EvImageMapping, 1);
1237                 
1238                 ev_image_mapping->image = ev_image_new_from_pixbuf (image_mapping->image);
1239                 ev_image_mapping->x1 = image_mapping->area.x1;
1240                 ev_image_mapping->x2 = image_mapping->area.x2;
1241                 ev_image_mapping->y1 = image_mapping->area.y1;
1242                 ev_image_mapping->y2 = image_mapping->area.y2;
1243
1244                 retval = g_list_prepend (retval, ev_image_mapping);
1245         }
1246
1247         poppler_page_free_image_mapping (mapping_list);
1248         g_object_unref (poppler_page);
1249
1250         return retval;
1251 }
1252
1253 static void
1254 pdf_document_document_images_iface_init (EvDocumentImagesIface *iface)
1255 {
1256         iface->get_images = pdf_document_images_get_images;
1257 }
1258
1259 static GdkPixbuf *
1260 make_thumbnail_for_page (PdfDocument     *pdf_document,
1261                          PopplerPage     *poppler_page, 
1262                          EvRenderContext *rc)
1263 {
1264         GdkPixbuf *pixbuf;
1265         int width, height;
1266
1267         pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
1268                                                 rc, &width, &height);
1269
1270         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
1271                                  width, height);
1272         gdk_pixbuf_fill (pixbuf, 0xffffffff);
1273
1274         ev_document_fc_mutex_lock ();
1275         poppler_page_render_to_pixbuf (poppler_page, 0, 0,
1276                                        width, height,
1277                                        rc->scale, rc->rotation, pixbuf);
1278         ev_document_fc_mutex_unlock ();
1279
1280         return pixbuf;
1281 }
1282
1283 static GdkPixbuf *
1284 pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
1285                                        EvRenderContext      *rc, 
1286                                        gboolean              border)
1287 {
1288         PdfDocument *pdf_document;
1289         PopplerPage *poppler_page;
1290         GdkPixbuf *pixbuf;
1291         GdkPixbuf *border_pixbuf;
1292
1293         pdf_document = PDF_DOCUMENT (document_thumbnails);
1294
1295         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1296         g_return_val_if_fail (poppler_page != NULL, NULL);
1297
1298         pixbuf = poppler_page_get_thumbnail (poppler_page);
1299         if (pixbuf) {
1300                 /* Rotate provided thumbnail if needed */
1301                 GdkPixbuf *rotated_pixbuf;
1302
1303                 rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
1304                                                            (GdkPixbufRotation) (360 - rc->rotation));
1305                 g_object_unref (pixbuf);
1306                 pixbuf = rotated_pixbuf;
1307         } else {
1308                 /* There is no provided thumbnail.  We need to make one. */
1309                 pixbuf = make_thumbnail_for_page (pdf_document, poppler_page, rc);
1310         }
1311
1312         if (border) {           
1313                 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
1314                 g_object_unref (pixbuf);
1315                 pixbuf = border_pixbuf;
1316         }               
1317
1318         g_object_unref (poppler_page);
1319         
1320         return pixbuf;
1321 }
1322
1323 static void
1324 pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
1325                                         EvRenderContext      *rc,
1326                                         gint                 *width,
1327                                         gint                 *height)
1328 {
1329         PdfDocument *pdf_document;
1330         PopplerPage *poppler_page;
1331         gint has_thumb;
1332         
1333         pdf_document = PDF_DOCUMENT (document_thumbnails);
1334         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1335
1336         g_return_if_fail (poppler_page != NULL);
1337
1338         has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
1339
1340         if (!has_thumb) {
1341                 double page_width, page_height;
1342
1343                 poppler_page_get_size (poppler_page, &page_width, &page_height);
1344
1345                 *width = (gint) MAX (page_width * rc->scale, 1);
1346                 *height = (gint) MAX (page_height * rc->scale, 1);
1347         }
1348         
1349         if (rc->rotation == 90 || rc->rotation == 270) {
1350                 gint  temp;
1351
1352                 temp = *width;
1353                 *width = *height;
1354                 *height = temp;
1355         }
1356         
1357         g_object_unref (poppler_page);
1358 }
1359
1360 static void
1361 pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
1362 {
1363         iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
1364         iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
1365 }
1366
1367
1368 static gboolean
1369 pdf_document_search_idle_callback (void *data)
1370 {
1371         PdfDocumentSearch *search = (PdfDocumentSearch*) data;
1372         PdfDocument *pdf_document = search->document;
1373         int n_pages;
1374         GList *matches;
1375         PopplerPage *page;
1376
1377         page = poppler_document_get_page (search->document->document,
1378                                           search->search_page);
1379
1380         ev_document_doc_mutex_lock ();
1381         matches = poppler_page_find_text (page, search->text);
1382         ev_document_doc_mutex_unlock ();
1383
1384         g_object_unref (page);
1385
1386         search->pages[search->search_page] = matches;
1387         ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
1388                                   search->search_page);
1389
1390         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
1391         search->search_page += 1;
1392         if (search->search_page == n_pages) {
1393                 /* wrap around */
1394                 search->search_page = 0;
1395         }
1396
1397         if (search->search_page != search->start_page) {
1398                 return TRUE;
1399         }
1400
1401         /* We're done. */
1402         search->idle = 0; /* will return FALSE to remove */
1403         return FALSE;
1404 }
1405
1406
1407 static PdfDocumentSearch *
1408 pdf_document_search_new (PdfDocument *pdf_document,
1409                          int          start_page,
1410                          const char  *text)
1411 {
1412         PdfDocumentSearch *search;
1413         int n_pages;
1414         int i;
1415
1416         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
1417
1418         search = g_new0 (PdfDocumentSearch, 1);
1419
1420         search->text = g_strdup (text);
1421         search->pages = g_new0 (GList *, n_pages);
1422         search->document = pdf_document;
1423
1424         /* We add at low priority so the progress bar repaints */
1425         search->idle = g_idle_add_full (G_PRIORITY_LOW,
1426                                         pdf_document_search_idle_callback,
1427                                         search,
1428                                         NULL);
1429
1430         search->start_page = start_page;
1431         search->search_page = start_page;
1432
1433         return search;
1434 }
1435
1436 static void
1437 pdf_document_find_begin (EvDocumentFind   *document,
1438                          int               page,
1439                          const char       *search_string,
1440                          gboolean          case_sensitive)
1441 {
1442         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1443
1444         /* FIXME handle case_sensitive (right now XPDF
1445          * code is always case insensitive for ASCII
1446          * and case sensitive for all other languaages)
1447          */
1448
1449         if (pdf_document->search &&
1450             strcmp (search_string, pdf_document->search->text) == 0)
1451                 return;
1452
1453         if (pdf_document->search)
1454                 pdf_document_search_free (pdf_document->search);
1455
1456         pdf_document->search = pdf_document_search_new (pdf_document,
1457                                                         page,
1458                                                         search_string);
1459 }
1460
1461 static int
1462 pdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
1463 {
1464         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1465
1466         if (search) {
1467                 return g_list_length (search->pages[page]);
1468         } else {
1469                 return 0;
1470         }
1471 }
1472
1473 static gboolean
1474 pdf_document_find_get_result (EvDocumentFind *document_find,
1475                               int             page,
1476                               int             n_result,
1477                               EvRectangle    *rectangle)
1478 {
1479         PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
1480         PdfDocumentSearch *search = pdf_document->search;
1481         PopplerPage *poppler_page;
1482         PopplerRectangle *r;
1483         double height;
1484
1485         if (search == NULL)
1486                 return FALSE;
1487
1488         r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
1489                                                   n_result);
1490         if (r == NULL)
1491                 return FALSE;
1492
1493         poppler_page = poppler_document_get_page (pdf_document->document, page);
1494         poppler_page_get_size (poppler_page, NULL, &height);
1495         rectangle->x1 = r->x1;
1496         rectangle->y1 = height - r->y2;
1497         rectangle->x2 = r->x2;
1498         rectangle->y2 = height - r->y1;
1499         g_object_unref (poppler_page);
1500                 
1501         return TRUE;
1502 }
1503
1504 static int
1505 pdf_document_find_page_has_results (EvDocumentFind *document_find,
1506                                     int             page)
1507 {
1508         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1509
1510         return search && search->pages[page] != NULL;
1511 }
1512
1513 static double
1514 pdf_document_find_get_progress (EvDocumentFind *document_find)
1515 {
1516         PdfDocumentSearch *search;
1517         int n_pages, pages_done;
1518
1519         search = PDF_DOCUMENT (document_find)->search;
1520
1521         if (search == NULL) {
1522                 return 0;
1523         }
1524
1525         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
1526         if (search->search_page > search->start_page) {
1527                 pages_done = search->search_page - search->start_page + 1;
1528         } else if (search->search_page == search->start_page) {
1529                 pages_done = n_pages;
1530         } else {
1531                 pages_done = n_pages - search->start_page + search->search_page;
1532         }
1533
1534         return pages_done / (double) n_pages;
1535 }
1536
1537 static void
1538 pdf_document_find_cancel (EvDocumentFind *document)
1539 {
1540         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1541
1542         if (pdf_document->search) {
1543                 pdf_document_search_free (pdf_document->search);
1544                 pdf_document->search = NULL;
1545         }
1546 }
1547
1548 static void
1549 pdf_document_find_iface_init (EvDocumentFindIface *iface)
1550 {
1551         iface->begin = pdf_document_find_begin;
1552         iface->get_n_results = pdf_document_find_get_n_results;
1553         iface->get_result = pdf_document_find_get_result;
1554         iface->page_has_results = pdf_document_find_page_has_results;
1555         iface->get_progress = pdf_document_find_get_progress;
1556         iface->cancel = pdf_document_find_cancel;
1557 }
1558
1559 static void
1560 pdf_print_context_free (PdfPrintContext *ctx)
1561 {
1562         if (!ctx)
1563                 return;
1564
1565 #ifdef HAVE_CAIRO_PRINT
1566         if (ctx->cr) {
1567                 cairo_destroy (ctx->cr);
1568                 ctx->cr = NULL;
1569         }
1570 #else
1571         if (ctx->ps_file) {
1572                 poppler_ps_file_free (ctx->ps_file);
1573                 ctx->ps_file = NULL;
1574         }
1575 #endif
1576         g_free (ctx);
1577 }
1578
1579 static void
1580 pdf_document_file_exporter_begin (EvFileExporter        *exporter,
1581                                   EvFileExporterContext *fc)
1582 {
1583         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1584         PdfPrintContext *ctx;
1585         gdouble width, height;
1586         gboolean landscape, change_orient = FALSE;
1587 #ifdef HAVE_CAIRO_PRINT
1588         cairo_surface_t *surface = NULL;
1589 #endif
1590         
1591         if (pdf_document->print_ctx)
1592                 pdf_print_context_free (pdf_document->print_ctx);
1593         pdf_document->print_ctx = g_new0 (PdfPrintContext, 1);
1594         ctx = pdf_document->print_ctx;
1595         ctx->format = fc->format;
1596         ctx->pages_per_sheet = fc->pages_per_sheet;
1597
1598         landscape = (fc->orientation == EV_FILE_EXPORTER_LANDSCAPE);
1599         change_orient = landscape;
1600         
1601         switch (fc->pages_per_sheet) {
1602                 default:
1603                 case 1:
1604                         ctx->pages_x = 1;
1605                         ctx->pages_y = 1;
1606                         break;
1607                 case 2:
1608                         landscape = !landscape;
1609                         ctx->pages_x = 1;
1610                         ctx->pages_y = 2;
1611                         break;
1612                 case 4:
1613                         ctx->pages_x = 2;
1614                         ctx->pages_y = 2;
1615                         break;
1616                 case 6:
1617                         landscape = !landscape;
1618                         ctx->pages_x = 2;
1619                         ctx->pages_y = 3;
1620                         break;
1621                 case 9:
1622                         ctx->pages_x = 3;
1623                         ctx->pages_y = 3;
1624                         break;
1625                 case 16:
1626                         ctx->pages_x = 4;
1627                         ctx->pages_y = 4;
1628                         break;
1629         }
1630
1631         ctx->landscape = landscape;
1632
1633         if (change_orient) {
1634                 width = fc->paper_height;
1635                 height = fc->paper_width;
1636         } else {
1637                 width = fc->paper_width;
1638                 height = fc->paper_height;
1639         }
1640
1641         if (landscape) {
1642                 gint tmp;
1643
1644                 tmp = ctx->pages_x;
1645                 ctx->pages_x = ctx->pages_y;
1646                 ctx->pages_y = tmp;
1647
1648                 ctx->page_width = height / ctx->pages_x;
1649                 ctx->page_height = width / ctx->pages_y;
1650         } else {
1651                 ctx->page_width = width / ctx->pages_x;
1652                 ctx->page_height = height / ctx->pages_y;
1653         }
1654
1655         ctx->pages_printed = 0;
1656
1657         switch (fc->format) {
1658                 case EV_FILE_FORMAT_PS:
1659 #ifdef HAVE_CAIRO_PS
1660                         surface = cairo_ps_surface_create (fc->filename, width, height);
1661 #else
1662                         ctx->ps_file = poppler_ps_file_new (pdf_document->document,
1663                                                             fc->filename, fc->first_page,
1664                                                             fc->last_page - fc->first_page + 1);
1665                         poppler_ps_file_set_paper_size (ctx->ps_file, fc->paper_width, fc->paper_height);
1666                         poppler_ps_file_set_duplex (ctx->ps_file, fc->duplex);
1667 #endif /* HAVE_CAIRO_PS */
1668                         break;
1669                 case EV_FILE_FORMAT_PDF:
1670 #ifdef HAVE_CAIRO_PDF
1671                         surface = cairo_pdf_surface_create (fc->filename, width, height);
1672 #endif
1673                         break;
1674                 default:
1675                         g_assert_not_reached ();
1676         }
1677
1678 #ifdef HAVE_CAIRO_PRINT
1679         ctx->cr = cairo_create (surface);
1680         if (landscape) {
1681                 cairo_matrix_t matrix;
1682                 
1683                 cairo_translate (ctx->cr, width, 0);
1684                 cairo_matrix_init (&matrix,
1685                                    0,  1,
1686                                    -1,  0,
1687                                    0,  0);
1688                 cairo_transform (ctx->cr, &matrix);
1689         }
1690         cairo_surface_destroy (surface);
1691 #endif
1692 }
1693
1694 static void
1695 pdf_document_file_exporter_do_page (EvFileExporter  *exporter,
1696                                     EvRenderContext *rc)
1697 {
1698         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1699         PdfPrintContext *ctx = pdf_document->print_ctx;
1700         PopplerPage *poppler_page;
1701 #ifdef HAVE_CAIRO_PRINT
1702         gdouble page_width, page_height;
1703         gint    x, y;
1704 #endif
1705
1706         g_return_if_fail (pdf_document->print_ctx != NULL);
1707
1708         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1709         
1710 #ifdef HAVE_CAIRO_PRINT
1711         x = (ctx->pages_printed % ctx->pages_per_sheet) % ctx->pages_x;
1712         y = (ctx->pages_printed % ctx->pages_per_sheet) / ctx->pages_x;
1713         poppler_page_get_size (poppler_page, &page_width, &page_height);
1714         
1715         cairo_save (ctx->cr);
1716         cairo_translate (ctx->cr,
1717                          x * ctx->page_width,
1718                          y * ctx->page_height);
1719         if (ctx->landscape) {
1720                 cairo_scale (ctx->cr,
1721                              ctx->page_height / page_height,
1722                              ctx->page_height / page_height);
1723         } else {
1724                 cairo_scale (ctx->cr,
1725                              ctx->page_width / page_width,
1726                              ctx->page_height / page_height);
1727         }
1728
1729 #ifdef HAVE_POPPLER_PAGE_RENDER
1730         poppler_page_render (poppler_page, ctx->cr);
1731 #endif
1732         ctx->pages_printed++;
1733                         
1734         if (ctx->pages_printed % ctx->pages_per_sheet == 0) {
1735                 cairo_show_page (ctx->cr);
1736         }
1737         cairo_restore (ctx->cr);
1738 #else /* HAVE_CAIRO_PRINT */
1739         if (ctx->format == EV_FILE_FORMAT_PS)
1740                 poppler_page_render_to_ps (poppler_page, ctx->ps_file);
1741 #endif /* HAVE_CAIRO_PRINT */
1742         
1743         g_object_unref (poppler_page);
1744 }
1745
1746 static void
1747 pdf_document_file_exporter_end (EvFileExporter *exporter)
1748 {
1749         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1750
1751         pdf_print_context_free (pdf_document->print_ctx);
1752         pdf_document->print_ctx = NULL;
1753 }
1754
1755 static EvFileExporterCapabilities
1756 pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
1757 {
1758         return  (EvFileExporterCapabilities) (
1759                 EV_FILE_EXPORTER_CAN_PAGE_SET |
1760                 EV_FILE_EXPORTER_CAN_COPIES |
1761                 EV_FILE_EXPORTER_CAN_COLLATE |
1762                 EV_FILE_EXPORTER_CAN_REVERSE |
1763                 EV_FILE_EXPORTER_CAN_SCALE |
1764 #ifdef HAVE_CAIRO_PRINT
1765 #ifdef HAVE_POPPLER_PAGE_RENDER
1766 #if GTK_CHECK_VERSION (2, 11, 1)
1767                 EV_FILE_EXPORTER_CAN_NUMBER_UP |
1768 #endif
1769 #endif
1770 #endif
1771                 
1772 #ifdef HAVE_CAIRO_PDF
1773 #ifdef HAVE_POPPLER_PAGE_RENDER
1774                 EV_FILE_EXPORTER_CAN_GENERATE_PDF |
1775 #endif
1776 #endif
1777                 EV_FILE_EXPORTER_CAN_GENERATE_PS);
1778 }
1779
1780 static void
1781 pdf_document_file_exporter_iface_init (EvFileExporterIface *iface)
1782 {
1783         iface->begin = pdf_document_file_exporter_begin;
1784         iface->do_page = pdf_document_file_exporter_do_page;
1785         iface->end = pdf_document_file_exporter_end;
1786         iface->get_capabilities = pdf_document_file_exporter_get_capabilities;
1787 }
1788
1789 static void
1790 pdf_selection_render_selection (EvSelection      *selection,
1791                                 EvRenderContext  *rc,
1792                                 cairo_surface_t **surface,
1793                                 EvRectangle      *points,
1794                                 EvRectangle      *old_points,
1795                                 GdkColor         *text,
1796                                 GdkColor         *base)
1797 {
1798         PdfDocument *pdf_document;
1799         double width_points, height_points;
1800         gint width, height;
1801
1802         pdf_document = PDF_DOCUMENT (selection);
1803         set_rc_data (pdf_document, rc);
1804
1805         poppler_page_get_size (POPPLER_PAGE (rc->data),
1806                                &width_points, &height_points);
1807         width = (int) ((width_points * rc->scale) + 0.5);
1808         height = (int) ((height_points * rc->scale) + 0.5);
1809
1810
1811 #ifdef HAVE_POPPLER_PAGE_RENDER
1812         cairo_t *cr;
1813
1814         if (*surface == NULL) {
1815                 *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1816                                                        width, height);
1817                 
1818         }
1819
1820         cr = cairo_create (*surface);
1821         cairo_scale (cr, rc->scale, rc->scale);
1822         cairo_surface_set_device_offset (*surface, 0, 0);
1823         memset (cairo_image_surface_get_data (*surface), 0x00,
1824                 cairo_image_surface_get_height (*surface) *
1825                 cairo_image_surface_get_stride (*surface));
1826         poppler_page_render_selection (POPPLER_PAGE (rc->data),
1827                                        cr,
1828                                        (PopplerRectangle *)points,
1829                                        (PopplerRectangle *)old_points,
1830                                        POPPLER_SELECTION_NORMAL, /* SelectionStyle */
1831                                        text,
1832                                        base);
1833         cairo_destroy (cr);
1834 #else /* HAVE_POPPLER_PAGE_RENDER */
1835         GdkPixbuf *pixbuf;
1836         
1837         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
1838                                  TRUE, 8,
1839                                  width, height);
1840
1841         poppler_page_render_selection_to_pixbuf (POPPLER_PAGE (rc->data),
1842                                                  rc->scale, rc->rotation, pixbuf,
1843                                                  (PopplerRectangle *)points,
1844                                                  (PopplerRectangle *)old_points,
1845                                                  POPPLER_SELECTION_NORMAL, /* SelectionStyle */
1846                                                  text,
1847                                                  base);
1848         if (*surface)
1849                 cairo_surface_destroy (*surface);
1850         *surface = ev_document_misc_surface_from_pixbuf (pixbuf);
1851         g_object_unref (pixbuf);
1852 #endif /* HAVE_POPPLER_PAGE_RENDER */
1853 }
1854
1855
1856 static GdkRegion *
1857 pdf_selection_get_selection_region (EvSelection     *selection,
1858                                     EvRenderContext *rc,
1859                                     EvRectangle     *points)
1860 {
1861         PdfDocument *pdf_document;
1862         GdkRegion *retval;
1863
1864         pdf_document = PDF_DOCUMENT (selection);
1865
1866         set_rc_data (pdf_document, rc);
1867
1868         retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
1869                                                     rc->scale,
1870                                                     (PopplerRectangle *) points);
1871         return retval;
1872 }
1873
1874 static GdkRegion *
1875 pdf_selection_get_selection_map (EvSelection     *selection,
1876                                  EvRenderContext *rc)
1877 {
1878         PdfDocument *pdf_document;
1879         PopplerPage *poppler_page;
1880         PopplerRectangle points;
1881         GdkRegion *retval;
1882
1883         pdf_document = PDF_DOCUMENT (selection);
1884         poppler_page = poppler_document_get_page (pdf_document->document,
1885                                                   rc->page);
1886
1887         points.x1 = 0.0;
1888         points.y1 = 0.0;
1889         poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
1890         retval = poppler_page_get_selection_region (poppler_page, 1.0, &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_selection_region = pdf_selection_get_selection_region;
1901         iface->get_selection_map = pdf_selection_get_selection_map;
1902 }
1903
1904 /* Page Transitions */
1905 static gdouble
1906 pdf_document_get_page_duration (EvDocumentTransition *trans,
1907                                 gint                  page)
1908 {
1909         PdfDocument *pdf_document;
1910         PopplerPage *poppler_page;
1911         gdouble      duration = -1;
1912
1913         pdf_document = PDF_DOCUMENT (trans);
1914         poppler_page = poppler_document_get_page (pdf_document->document, page);
1915         if (!poppler_page)
1916                 return -1;
1917
1918         duration = poppler_page_get_duration (poppler_page);
1919         g_object_unref (poppler_page);
1920
1921         return duration;
1922 }
1923
1924 static void
1925 pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface)
1926 {
1927         iface->get_page_duration = pdf_document_get_page_duration;
1928 }
1929
1930 PdfDocument *
1931 pdf_document_new (void)
1932 {
1933         return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
1934 }
1935
1936 /* Forms */
1937 static void
1938 pdf_document_get_crop_box (EvDocument  *document, 
1939                            int          page, 
1940                            EvRectangle *rect)
1941 {
1942         PdfDocument *pdf_document;
1943         PopplerPage *poppler_page;
1944         PopplerRectangle poppler_rect;
1945
1946         pdf_document = PDF_DOCUMENT (document);
1947         poppler_page = poppler_document_get_page (pdf_document->document, page);
1948         poppler_page_get_crop_box (poppler_page, &poppler_rect);
1949         rect->x1 = poppler_rect.x1;
1950         rect->x2 = poppler_rect.x2;
1951         rect->y1 = poppler_rect.y1;
1952         rect->y2 = poppler_rect.y2;
1953 }
1954
1955 #ifdef HAVE_FORMS
1956 static EvFormField *
1957 ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
1958 {
1959         EvFormField *ev_field = NULL;
1960         gint         id;
1961         gdouble      font_size;
1962         gboolean     is_read_only;
1963
1964         id = poppler_form_field_get_id (poppler_field);
1965         font_size = poppler_form_field_get_font_size (poppler_field);
1966         is_read_only = poppler_form_field_is_read_only (poppler_field);
1967
1968         switch (poppler_form_field_get_field_type (poppler_field)) {
1969                 case POPPLER_FORM_FIELD_TEXT: {
1970                         EvFormFieldText    *field_text;
1971                         EvFormFieldTextType ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1972
1973                         switch (poppler_form_field_text_get_text_type (poppler_field)) {
1974                                 case POPPLER_FORM_TEXT_NORMAL:
1975                                         ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1976                                         break;
1977                                 case POPPLER_FORM_TEXT_MULTILINE:
1978                                         ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
1979                                         break;
1980                                 case POPPLER_FORM_TEXT_FILE_SELECT:
1981                                         ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
1982                                         break;
1983                         }
1984                         
1985                         ev_field = ev_form_field_text_new (id, ev_text_type);
1986                         field_text = EV_FORM_FIELD_TEXT (ev_field);
1987
1988                         field_text->do_spell_check = poppler_form_field_text_do_spell_check (poppler_field);
1989                         field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
1990                         field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
1991                         field_text->is_password = poppler_form_field_text_is_password (poppler_field);
1992                         
1993 #ifdef HAVE_POPPLER_FORM_FIELD_TEXT_GET_MAX_LEN
1994                         field_text->max_len = poppler_form_field_text_get_max_len (poppler_field);
1995 #endif
1996                         field_text->text = poppler_form_field_text_get_text (poppler_field);
1997
1998                 }
1999                         break;
2000                 case POPPLER_FORM_FIELD_BUTTON: {
2001                         EvFormFieldButton    *field_button;
2002                         EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2003
2004                         switch (poppler_form_field_button_get_button_type (poppler_field)) {
2005                                 case POPPLER_FORM_BUTTON_PUSH:
2006                                         ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2007                                         break;
2008                                 case POPPLER_FORM_BUTTON_CHECK:
2009                                         ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
2010                                         break;
2011                                 case POPPLER_FORM_BUTTON_RADIO:
2012                                         ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
2013                                         break;
2014                         }
2015
2016                         ev_field = ev_form_field_button_new (id, ev_button_type);
2017                         field_button = EV_FORM_FIELD_BUTTON (ev_field);
2018                         
2019                         field_button->state = poppler_form_field_button_get_state (poppler_field);
2020                 }
2021                         break;
2022                 case POPPLER_FORM_FIELD_CHOICE: {
2023                         EvFormFieldChoice    *field_choice;
2024                         EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2025
2026                         switch (poppler_form_field_choice_get_choice_type (poppler_field)) {
2027                                 case POPPLER_FORM_CHOICE_COMBO:
2028                                         ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2029                                         break;
2030                                 case EV_FORM_FIELD_CHOICE_LIST:
2031                                         ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
2032                                         break;
2033                         }
2034
2035                         ev_field = ev_form_field_choice_new (id, ev_choice_type);
2036                         field_choice = EV_FORM_FIELD_CHOICE (ev_field);
2037
2038                         field_choice->is_editable = poppler_form_field_choice_is_editable (poppler_field);
2039                         field_choice->multi_select = poppler_form_field_choice_can_select_multiple (poppler_field);
2040                         field_choice->do_spell_check = poppler_form_field_choice_do_spell_check (poppler_field);
2041                         field_choice->commit_on_sel_change = poppler_form_field_choice_commit_on_change (poppler_field);
2042
2043                         /* TODO: we need poppler_form_field_choice_get_selected_items in poppler 
2044                         field_choice->selected_items = poppler_form_field_choice_get_selected_items (poppler_field);*/
2045                         if (field_choice->is_editable)
2046                                 field_choice->text = poppler_form_field_choice_get_text (poppler_field);
2047                 }
2048                         break;
2049                 case POPPLER_FORM_FIELD_SIGNATURE:
2050                         /* TODO */
2051                         ev_field = ev_form_field_signature_new (id);
2052                         break;
2053                 case POPPLER_FORM_FIELD_UNKNOWN:
2054                         break;
2055         }
2056
2057         ev_field->font_size = font_size;
2058         ev_field->is_read_only = is_read_only;
2059
2060         return ev_field;
2061 }
2062
2063 static GList *
2064 pdf_document_forms_get_form_fields (EvDocumentForms *document, 
2065                                     gint             page)
2066 {
2067         PdfDocument *pdf_document;
2068         PopplerPage *poppler_page;
2069         GList *retval = NULL;
2070         GList *fields;
2071         GList *list;
2072         double height;
2073         
2074
2075         pdf_document = PDF_DOCUMENT (document);
2076         poppler_page = poppler_document_get_page (pdf_document->document, page);
2077         fields = poppler_page_get_form_field_mapping (poppler_page);
2078         poppler_page_get_size (poppler_page, NULL, &height);
2079
2080         for (list = fields; list; list = list->next) {
2081                 PopplerFormFieldMapping *mapping;
2082                 EvFormFieldMapping *field_mapping;
2083                 
2084                 mapping = (PopplerFormFieldMapping *)list->data;
2085
2086                 field_mapping = g_new0 (EvFormFieldMapping, 1);
2087                 field_mapping->x1 = mapping->area.x1;
2088                 field_mapping->x2 = mapping->area.x2;
2089                 field_mapping->y1 = height - mapping->area.y2;
2090                 field_mapping->y2 = height - mapping->area.y1;
2091                 field_mapping->field = ev_form_field_from_poppler_field (mapping->field);
2092                 field_mapping->field->page = page;
2093                 
2094                 retval = g_list_prepend (retval, field_mapping);
2095         }
2096         poppler_page_free_form_field_mapping (fields);
2097         g_object_unref (poppler_page);
2098
2099         return g_list_reverse (retval);
2100 }
2101
2102 static gchar *
2103 pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
2104                                              EvFormField     *field)
2105         
2106 {
2107         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2108         PopplerFormField *poppler_field;
2109         gchar *text;
2110
2111         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2112         if (!poppler_field)
2113                 return NULL;
2114         
2115         text = poppler_form_field_text_get_text (poppler_field);
2116         g_object_unref (poppler_field);
2117
2118         return text;
2119 }
2120
2121 static void
2122 pdf_document_forms_form_field_text_set_text (EvDocumentForms *document, 
2123                                              EvFormField     *field,
2124                                              const gchar     *text)
2125 {
2126         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2127         PopplerFormField *poppler_field;
2128
2129         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2130         if (!poppler_field)
2131                 return;
2132         poppler_form_field_text_set_text (poppler_field, text);
2133         g_object_unref (poppler_field);
2134 }
2135
2136 static void
2137 pdf_document_forms_form_field_button_set_state (EvDocumentForms *document, 
2138                                                 EvFormField     *field,
2139                                                 gboolean         state)
2140 {
2141         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2142         PopplerFormField *poppler_field;
2143
2144         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2145         if (!poppler_field)
2146                 return;
2147         
2148         poppler_form_field_button_set_state (poppler_field, state);
2149         g_object_unref (poppler_field);
2150 }
2151
2152 static gboolean
2153 pdf_document_forms_form_field_button_get_state (EvDocumentForms *document, 
2154                                                 EvFormField     *field)
2155 {
2156         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2157         PopplerFormField *poppler_field;
2158         gboolean state;
2159
2160         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2161         if (!poppler_field)
2162                 return FALSE;
2163
2164         state = poppler_form_field_button_get_state (poppler_field);
2165         g_object_unref (poppler_field);
2166
2167         return state;
2168 }
2169
2170 static gchar *
2171 pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document, 
2172                                                EvFormField     *field,
2173                                                gint             index)
2174 {
2175         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2176         PopplerFormField *poppler_field;
2177         gchar *text;
2178
2179         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2180         if (!poppler_field)
2181                 return NULL;
2182
2183         text = poppler_form_field_choice_get_item (poppler_field, index);
2184         g_object_unref (poppler_field);
2185
2186         return text;
2187 }
2188
2189 static int
2190 pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document, 
2191                                                   EvFormField     *field)
2192 {
2193         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2194         PopplerFormField *poppler_field;
2195         gint n_items;
2196
2197         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2198         if (!poppler_field)
2199                 return -1;
2200         
2201         n_items = poppler_form_field_choice_get_n_items (poppler_field);
2202         g_object_unref (poppler_field);
2203
2204         return n_items;
2205 }
2206
2207 static gboolean
2208 pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document, 
2209                                                        EvFormField     *field,
2210                                                        gint             index)
2211 {
2212         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2213         PopplerFormField *poppler_field;
2214         gboolean selected;
2215
2216         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2217         if (!poppler_field)
2218                 return FALSE;
2219
2220         selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
2221         g_object_unref (poppler_field);
2222
2223         return selected;
2224 }
2225
2226 static void
2227 pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document, 
2228                                                   EvFormField     *field,
2229                                                   gint             index)
2230 {
2231         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2232         PopplerFormField *poppler_field;
2233
2234         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2235         if (!poppler_field)
2236                 return;
2237
2238         poppler_form_field_choice_select_item (poppler_field, index);
2239         g_object_unref (poppler_field);
2240 }
2241
2242 static void
2243 pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document, 
2244                                                   EvFormField     *field,
2245                                                   gint             index)
2246 {
2247         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2248         PopplerFormField *poppler_field;
2249
2250         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2251         if (!poppler_field)
2252                 return;
2253
2254         poppler_form_field_choice_toggle_item (poppler_field, index);
2255         g_object_unref (poppler_field);
2256 }
2257
2258 static void
2259 pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document, 
2260                                                    EvFormField     *field)
2261 {
2262         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2263         PopplerFormField *poppler_field;
2264
2265         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2266         if (!poppler_field)
2267                 return;
2268         
2269         poppler_form_field_choice_unselect_all (poppler_field);
2270         g_object_unref (poppler_field);
2271 }
2272
2273 static void
2274 pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
2275                                                EvFormField     *field,
2276                                                const gchar     *text)
2277 {
2278         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2279         PopplerFormField *poppler_field;
2280
2281         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2282         if (!poppler_field)
2283                 return;
2284         
2285         poppler_form_field_choice_set_text (poppler_field, text);
2286         g_object_unref (poppler_field);
2287 }
2288
2289 static gchar *
2290 pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
2291                                                EvFormField     *field)
2292 {
2293         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2294         PopplerFormField *poppler_field;
2295         gchar *text;
2296
2297         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2298         if (!poppler_field)
2299                 return NULL;
2300
2301         text = poppler_form_field_choice_get_text (poppler_field);
2302         g_object_unref (poppler_field);
2303
2304         return text;
2305 }
2306
2307 static void
2308 pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface)
2309 {
2310         iface->get_form_fields = pdf_document_forms_get_form_fields;
2311         iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text;
2312         iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text;
2313         iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state;
2314         iface->form_field_button_get_state = pdf_document_forms_form_field_button_get_state;
2315         iface->form_field_choice_get_item = pdf_document_forms_form_field_choice_get_item;
2316         iface->form_field_choice_get_n_items = pdf_document_forms_form_field_choice_get_n_items;
2317         iface->form_field_choice_is_item_selected = pdf_document_forms_form_field_choice_is_item_selected;
2318         iface->form_field_choice_select_item = pdf_document_forms_form_field_choice_select_item;
2319         iface->form_field_choice_toggle_item = pdf_document_forms_form_field_choice_toggle_item;
2320         iface->form_field_choice_unselect_all = pdf_document_forms_form_field_choice_unselect_all;
2321         iface->form_field_choice_set_text = pdf_document_forms_form_field_choice_set_text;
2322         iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text;
2323 }
2324 #endif /* HAVE_FORMS */