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