]> www.fi.muni.cz Git - evince.git/blob - pdf/ev-poppler.cc
Updated Turkish Translation
[evince.git] / 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 <math.h>
21 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <poppler.h>
24 #include <poppler-document.h>
25 #include <poppler-page.h>
26 #include <glib/gi18n.h>
27
28 #include "ev-poppler.h"
29 #include "ev-ps-exporter.h"
30 #include "ev-document-find.h"
31 #include "ev-document-misc.h"
32 #include "ev-document-links.h"
33 #include "ev-document-fonts.h"
34 #include "ev-document-security.h"
35 #include "ev-document-thumbnails.h"
36 #include "ev-selection.h"
37 #include "ev-attachment.h"
38
39 typedef struct {
40         PdfDocument *document;
41         char *text;
42         GList **pages;
43         guint idle;
44         int start_page;
45         int search_page;
46 } PdfDocumentSearch;
47
48 struct _PdfDocumentClass
49 {
50         GObjectClass parent_class;
51 };
52
53 struct _PdfDocument
54 {
55         GObject parent_instance;
56
57         PopplerDocument *document;
58         PopplerPSFile *ps_file;
59         gchar *password;
60
61         PopplerFontInfo *font_info;
62         PopplerFontsIter *fonts_iter;
63         int fonts_scanned_pages;
64
65         PdfDocumentSearch *search;
66 };
67
68 static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
69 static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
70 static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
71 static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
72 static void pdf_document_document_fonts_iface_init      (EvDocumentFontsIface      *iface);
73 static void pdf_document_find_iface_init                (EvDocumentFindIface       *iface);
74 static void pdf_document_ps_exporter_iface_init         (EvPSExporterIface         *iface);
75 static void pdf_selection_iface_init                    (EvSelectionIface          *iface);
76 static void pdf_document_thumbnails_get_dimensions      (EvDocumentThumbnails      *document_thumbnails,
77                                                          gint                       page,
78                                                          gint                       size,
79                                                          gint                      *width,
80                                                          gint                      *height);
81 static int  pdf_document_get_n_pages                    (EvDocument                *document);
82
83 static EvLinkDest *ev_link_dest_from_dest   (PdfDocument       *pdf_document,
84                                              PopplerDest       *dest);
85 static EvLink     *ev_link_from_action      (PdfDocument       *pdf_document,
86                                              PopplerAction     *action);
87 static void        pdf_document_search_free (PdfDocumentSearch *search);
88
89
90 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
91                          {
92                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
93                                                         pdf_document_document_iface_init);
94                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
95                                                         pdf_document_security_iface_init);
96                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
97                                                         pdf_document_document_thumbnails_iface_init);
98                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
99                                                         pdf_document_document_links_iface_init);
100                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
101                                                         pdf_document_document_fonts_iface_init);
102                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
103                                                         pdf_document_find_iface_init);
104                                  G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER,
105                                                         pdf_document_ps_exporter_iface_init);
106                                  G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
107                                                         pdf_selection_iface_init);
108                          });
109
110
111 static void
112 set_rc_data (PdfDocument     *pdf_document,
113              EvRenderContext *rc)
114 {
115         if (rc->data == NULL) {
116                 rc->data = poppler_document_get_page (pdf_document->document,
117                                                       rc->page);
118                 rc->destroy = g_object_unref;
119         } else {
120                 g_assert (rc->page == poppler_page_get_index (POPPLER_PAGE (rc->data)));
121         }
122 }
123
124 static void
125 pdf_document_search_free (PdfDocumentSearch   *search)
126 {
127         PdfDocument *pdf_document = search->document;
128         int n_pages;
129         int i;
130
131         if (search->idle != 0)
132                 g_source_remove (search->idle);
133
134         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
135         for (i = 0; i < n_pages; i++) {
136                 g_list_foreach (search->pages[i], (GFunc) g_free, NULL);
137                 g_list_free (search->pages[i]);
138         }
139         
140         g_free (search->text);
141 }
142
143 static void
144 pdf_document_dispose (GObject *object)
145 {
146         PdfDocument *pdf_document = PDF_DOCUMENT(object);
147
148         if (pdf_document->search) {
149                 pdf_document_search_free (pdf_document->search);
150                 pdf_document->search = NULL;
151         }
152
153         if (pdf_document->document) {
154                 g_object_unref (pdf_document->document);
155         }
156
157         if (pdf_document->font_info) { 
158                 poppler_font_info_free (pdf_document->font_info);
159         }
160
161         if (pdf_document->fonts_iter) {
162                 poppler_fonts_iter_free (pdf_document->fonts_iter);
163         }
164 }
165
166 static void
167 pdf_document_class_init (PdfDocumentClass *klass)
168 {
169         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
170
171         g_object_class->dispose = pdf_document_dispose;
172 }
173
174 static void
175 pdf_document_init (PdfDocument *pdf_document)
176 {
177         pdf_document->password = NULL;
178 }
179
180 static void
181 convert_error (GError  *poppler_error,
182                GError **error)
183 {
184         if (poppler_error == NULL)
185                 return;
186
187         if (poppler_error->domain == POPPLER_ERROR) {
188                 /* convert poppler errors into EvDocument errors */
189                 gint code = EV_DOCUMENT_ERROR_INVALID;
190                 if (poppler_error->code == POPPLER_ERROR_INVALID)
191                         code = EV_DOCUMENT_ERROR_INVALID;
192                 else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED)
193                         code = EV_DOCUMENT_ERROR_ENCRYPTED;
194                         
195
196                 g_set_error (error,
197                              EV_DOCUMENT_ERROR,
198                              code,
199                              poppler_error->message,
200                              NULL);
201         } else {
202                 g_propagate_error (error, poppler_error);
203         }
204 }
205
206
207 /* EvDocument */
208 static gboolean
209 pdf_document_save (EvDocument  *document,
210                    const char  *uri,
211                    GError     **error)
212 {
213         gboolean retval;
214         GError *poppler_error = NULL;
215
216         retval = poppler_document_save (PDF_DOCUMENT (document)->document,
217                                         uri,
218                                         &poppler_error);
219         if (! retval)
220                 convert_error (poppler_error, error);
221
222         return retval;
223 }
224
225 static gboolean
226 pdf_document_load (EvDocument   *document,
227                    const char   *uri,
228                    GError      **error)
229 {
230         GError *poppler_error = NULL;
231         PdfDocument *pdf_document = PDF_DOCUMENT (document);
232
233         pdf_document->document =
234                 poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
235
236         if (pdf_document->document == NULL) {
237                 convert_error (poppler_error, error);
238                 return FALSE;
239         }
240
241         return TRUE;
242 }
243
244 static int
245 pdf_document_get_n_pages (EvDocument *document)
246 {
247         return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
248 }
249
250 static void
251 pdf_document_get_page_size (EvDocument   *document,
252                             int           page,
253                             double       *width,
254                             double       *height)
255 {
256         PdfDocument *pdf_document = PDF_DOCUMENT (document);
257         PopplerPage *poppler_page;
258
259         poppler_page = poppler_document_get_page (pdf_document->document, page);
260         poppler_page_get_size (poppler_page, width, height);
261         g_object_unref (poppler_page);
262 }
263
264 static char *
265 pdf_document_get_page_label (EvDocument *document,
266                              int         page)
267 {
268         PopplerPage *poppler_page;
269         char *label = NULL;
270
271         poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document,
272                                                   page);
273
274         g_object_get (G_OBJECT (poppler_page),
275                       "label", &label,
276                       NULL);
277         g_object_unref (poppler_page);
278
279         return label;
280 }
281
282 static gboolean
283 pdf_document_has_attachments (EvDocument *document)
284 {
285         PdfDocument *pdf_document;
286
287         pdf_document = PDF_DOCUMENT (document);
288
289         return poppler_document_has_attachments (pdf_document->document);
290 }
291
292 struct SaveToBufferData {
293         gchar *buffer;
294         gsize len, max;
295 };
296
297 static gboolean
298 attachment_save_to_buffer_callback (const gchar  *buf,
299                                     gsize         count,
300                                     gpointer      user_data,
301                                     GError      **error)
302 {
303         struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
304         gchar *new_buffer;
305         gsize new_max;
306
307         if (sdata->len + count > sdata->max) {
308                 new_max = MAX (sdata->max * 2, sdata->len + count);
309                 new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
310
311                 sdata->buffer = new_buffer;
312                 sdata->max = new_max;
313         }
314         
315         memcpy (sdata->buffer + sdata->len, buf, count);
316         sdata->len += count;
317         
318         return TRUE;
319 }
320
321 static gboolean
322 attachment_save_to_buffer (PopplerAttachment  *attachment,
323                            gchar             **buffer,
324                            gsize              *buffer_size,
325                            GError            **error)
326 {
327         static const gint initial_max = 1024;
328         struct SaveToBufferData sdata;
329
330         *buffer = NULL;
331         *buffer_size = 0;
332
333         sdata.buffer = (gchar *) g_malloc (initial_max);
334         sdata.max = initial_max;
335         sdata.len = 0;
336
337         if (! poppler_attachment_save_to_callback (attachment,
338                                                    attachment_save_to_buffer_callback,
339                                                    &sdata,
340                                                    error)) {
341                 g_free (sdata.buffer);
342                 return FALSE;
343         }
344
345         *buffer = sdata.buffer;
346         *buffer_size = sdata.len;
347         
348         return TRUE;
349 }
350
351 static GList *
352 pdf_document_get_attachments (EvDocument *document)
353 {
354         PdfDocument *pdf_document;
355         GList *attachments;
356         GList *list;
357         GList *retval = NULL;
358
359         pdf_document = PDF_DOCUMENT (document);
360
361         if (!pdf_document_has_attachments (document))
362                 return NULL;
363
364         attachments = poppler_document_get_attachments (pdf_document->document);
365         
366         for (list = attachments; list; list = list->next) {
367                 PopplerAttachment *attachment;
368                 EvAttachment *ev_attachment;
369                 gchar *data = NULL;
370                 gsize size;
371                 GError *error = NULL;
372
373                 attachment = (PopplerAttachment *) list->data;
374
375                 if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
376                         ev_attachment = ev_attachment_new (attachment->name,
377                                                            attachment->description,
378                                                            attachment->mtime,
379                                                            attachment->ctime,
380                                                            size, data);
381                         
382                         retval = g_list_prepend (retval, ev_attachment);
383                 } else {
384                         if (error) {
385                                 g_warning ("%s", error->message);
386                                 g_error_free (error);
387
388                                 g_free (data);
389                         }
390                 }
391
392                 g_object_unref (attachment);
393         }
394
395         return g_list_reverse (retval);
396 }
397
398 static GdkPixbuf *
399 pdf_document_render_pixbuf (EvDocument   *document,
400                             EvRenderContext *rc)
401 {
402         PdfDocument *pdf_document;
403         GdkPixbuf *pixbuf;
404         double width_points, height_points;
405         gint width, height;
406
407         pdf_document = PDF_DOCUMENT (document);
408
409         set_rc_data (pdf_document, rc);
410
411         poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
412
413         if (rc->rotation == 90 || rc->rotation == 270) {
414                 width = (int) ((height_points * rc->scale) + 0.5);
415                 height = (int) ((width_points * rc->scale) + 0.5);
416         } else {
417                 width = (int) ((width_points * rc->scale) + 0.5);
418                 height = (int) ((height_points * rc->scale) + 0.5);
419         }
420
421         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
422                                  FALSE, 8,
423                                  width, height);
424
425         poppler_page_render_to_pixbuf (POPPLER_PAGE (rc->data),
426                                        0, 0,
427                                        width, height,
428                                        rc->scale,
429                                        rc->rotation,
430                                        pixbuf);
431         
432         
433         return pixbuf;
434 }
435
436 /* EvDocumentSecurity */
437
438 static gboolean
439 pdf_document_has_document_security (EvDocumentSecurity *document_security)
440 {
441         /* FIXME: do we really need to have this? */
442         return FALSE;
443 }
444
445 static void
446 pdf_document_set_password (EvDocumentSecurity *document_security,
447                            const char         *password)
448 {
449         PdfDocument *document = PDF_DOCUMENT (document_security);
450
451         if (document->password)
452                 g_free (document->password);
453
454         document->password = g_strdup (password);
455 }
456
457 static gboolean
458 pdf_document_can_get_text (EvDocument *document)
459 {
460         return TRUE;
461 }
462
463 static EvDocumentInfo *
464 pdf_document_get_info (EvDocument *document)
465 {
466         EvDocumentInfo *info;
467         PopplerPageLayout layout;
468         PopplerPageMode mode;
469         PopplerViewerPreferences view_prefs;
470         PopplerPermissions permissions;
471
472         info = g_new0 (EvDocumentInfo, 1);
473
474         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
475                             EV_DOCUMENT_INFO_FORMAT |
476                             EV_DOCUMENT_INFO_AUTHOR |
477                             EV_DOCUMENT_INFO_SUBJECT |
478                             EV_DOCUMENT_INFO_KEYWORDS |
479                             EV_DOCUMENT_INFO_LAYOUT |
480                             EV_DOCUMENT_INFO_START_MODE |
481                             EV_DOCUMENT_INFO_PERMISSIONS |
482                             EV_DOCUMENT_INFO_UI_HINTS |
483                             EV_DOCUMENT_INFO_CREATOR |
484                             EV_DOCUMENT_INFO_PRODUCER |
485                             EV_DOCUMENT_INFO_CREATION_DATE |
486                             EV_DOCUMENT_INFO_MOD_DATE |
487                             EV_DOCUMENT_INFO_LINEARIZED |
488                             EV_DOCUMENT_INFO_N_PAGES |
489                             EV_DOCUMENT_INFO_SECURITY;
490
491
492         g_object_get (PDF_DOCUMENT (document)->document,
493                       "title", &(info->title),
494                       "format", &(info->format),
495                       "author", &(info->author),
496                       "subject", &(info->subject),
497                       "keywords", &(info->keywords),
498                       "page-mode", &mode,
499                       "page-layout", &layout,
500                       "viewer-preferences", &view_prefs,
501                       "permissions", &permissions,
502                       "creator", &(info->creator),
503                       "producer", &(info->producer),
504                       "creation-date", &(info->creation_date),
505                       "mod-date", &(info->modified_date),
506                       "linearized", &(info->linearized),
507                       NULL);
508
509         switch (layout) {
510                 case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
511                         info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
512                         break;
513                 case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
514                         info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
515                         break;
516                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
517                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
518                         break;
519                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
520                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
521                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
522                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
523                         break;
524                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
525                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
526                         break;
527                 default:
528                         break;
529         }
530
531         switch (mode) {
532                 case POPPLER_PAGE_MODE_NONE:
533                         info->mode = EV_DOCUMENT_MODE_NONE;
534                         break;
535                 case POPPLER_PAGE_MODE_USE_THUMBS:
536                         info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
537                         break;
538                 case POPPLER_PAGE_MODE_USE_OC:
539                         info->mode = EV_DOCUMENT_MODE_USE_OC;
540                         break;
541                 case POPPLER_PAGE_MODE_FULL_SCREEN:
542                         info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
543                         break;
544                 case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
545                         info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
546                 default:
547                         break;
548         }
549
550         info->ui_hints = 0;
551         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
552                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
553         }
554         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
555                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
556         }
557         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
558                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
559         }
560         if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
561                 info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
562         }
563         if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
564                 info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
565         }
566         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
567                 info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
568         }
569         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
570                 info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
571         }
572
573         info->permissions = 0;
574         if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
575                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
576         }
577         if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
578                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
579         }
580         if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
581                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
582         }
583         if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
584                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
585         }
586
587         info->n_pages = ev_document_get_n_pages (document);
588
589         if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) {
590                 /* translators: this is the document security state */
591                 info->security = g_strdup (_("Yes"));
592         } else {
593                 /* translators: this is the document security state */
594                 info->security = g_strdup (_("No"));
595         }
596
597         return info;
598 }
599
600 static char *
601 pdf_document_get_text (EvDocument *document, int page, EvRectangle *rect)
602 {
603         PdfDocument *pdf_document = PDF_DOCUMENT (document);
604         PopplerPage *poppler_page;
605         PopplerRectangle r;
606         double height;
607         char *text;
608         
609         poppler_page = poppler_document_get_page (pdf_document->document, page);
610         g_return_val_if_fail (poppler_page != NULL, NULL);
611
612         poppler_page_get_size (poppler_page, NULL, &height);
613         r.x1 = rect->x1;
614         r.y1 = height - rect->y2;
615         r.x2 = rect->x2;
616         r.y2 = height - rect->y1;
617
618         text = poppler_page_get_text (poppler_page, &r);
619
620         g_object_unref (poppler_page);
621
622         return text;
623 }
624
625 static void
626 pdf_document_document_iface_init (EvDocumentIface *iface)
627 {
628         iface->save = pdf_document_save;
629         iface->load = pdf_document_load;
630         iface->get_n_pages = pdf_document_get_n_pages;
631         iface->get_page_size = pdf_document_get_page_size;
632         iface->get_page_label = pdf_document_get_page_label;
633         iface->has_attachments = pdf_document_has_attachments;
634         iface->get_attachments = pdf_document_get_attachments;
635         iface->render_pixbuf = pdf_document_render_pixbuf;
636         iface->get_text = pdf_document_get_text;
637         iface->can_get_text = pdf_document_can_get_text;
638         iface->get_info = pdf_document_get_info;
639 };
640
641 static void
642 pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
643 {
644         iface->has_document_security = pdf_document_has_document_security;
645         iface->set_password = pdf_document_set_password;
646 }
647
648 static gdouble
649 pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
650 {
651         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
652         int n_pages;
653
654         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
655
656         return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
657 }
658
659 static gboolean
660 pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
661                          int              n_pages)
662 {
663         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
664         gboolean result;
665
666         g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
667
668         if (pdf_document->font_info == NULL) { 
669                 pdf_document->font_info = poppler_font_info_new (pdf_document->document);
670         }
671
672         if (pdf_document->fonts_iter) {
673                 poppler_fonts_iter_free (pdf_document->fonts_iter);
674         }
675
676         pdf_document->fonts_scanned_pages += n_pages;
677
678         result = poppler_font_info_scan (pdf_document->font_info, n_pages,
679                                          &pdf_document->fonts_iter);
680         if (!result) {
681                 pdf_document->fonts_scanned_pages = 0;
682                 poppler_font_info_free (pdf_document->font_info);
683                 pdf_document->font_info = NULL; 
684         }
685
686         return result;
687 }
688
689 static const char *
690 font_type_to_string (PopplerFontType type)
691 {
692         switch (type) {
693                 case POPPLER_FONT_TYPE_TYPE1:
694                         return _("Type 1");
695                 case POPPLER_FONT_TYPE_TYPE1C:
696                         return _("Type 1C");
697                 case POPPLER_FONT_TYPE_TYPE3:
698                         return _("Type 3");
699                 case POPPLER_FONT_TYPE_TRUETYPE:
700                         return _("TrueType");
701                 case POPPLER_FONT_TYPE_CID_TYPE0:
702                         return _("Type 1 (CID)");
703                 case POPPLER_FONT_TYPE_CID_TYPE0C:
704                         return _("Type 1C (CID)");
705                 case POPPLER_FONT_TYPE_CID_TYPE2:
706                         return _("TrueType (CID)");
707                 default:
708                         return _("Unknown font type");
709         }
710 }
711
712 static void
713 pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
714                                GtkTreeModel    *model)
715 {
716         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
717         PopplerFontsIter *iter = pdf_document->fonts_iter;
718
719         g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
720
721         if (!iter)
722                 return;
723
724         do {
725                 GtkTreeIter list_iter;
726                 const char *name;
727                 const char *type;
728                 const char *embedded;
729                 char *details;
730                 
731                 name = poppler_fonts_iter_get_name (iter);
732
733                 if (name == NULL) {
734                         name = _("No name");
735                 }
736
737                 type = font_type_to_string (
738                         poppler_fonts_iter_get_font_type (iter));
739
740                 if (poppler_fonts_iter_is_embedded (iter)) {
741                         if (poppler_fonts_iter_is_subset (iter))
742                                 embedded = _("Embedded subset");
743                         else
744                                 embedded = _("Embedded");
745                 } else {
746                         embedded = _("Not embedded");
747                 }
748
749                 details = g_markup_printf_escaped ("%s\n%s", type, embedded);
750
751                 gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
752                 gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
753                                     EV_DOCUMENT_FONTS_COLUMN_NAME, name,
754                                     EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
755                                     -1);
756
757                 g_free (details);
758         } while (poppler_fonts_iter_next (iter));
759 }
760
761 static void
762 pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface)
763 {
764         iface->fill_model = pdf_document_fonts_fill_model;
765         iface->scan = pdf_document_fonts_scan;
766         iface->get_progress = pdf_document_fonts_get_progress;
767 }
768
769 static gboolean
770 pdf_document_links_has_document_links (EvDocumentLinks *document_links)
771 {
772         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
773         PopplerIndexIter *iter;
774
775         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
776
777         iter = poppler_index_iter_new (pdf_document->document);
778         if (iter == NULL)
779                 return FALSE;
780         poppler_index_iter_free (iter);
781
782         return TRUE;
783 }
784
785 static EvLinkDest *
786 ev_link_dest_from_dest (PdfDocument *pdf_document,
787                         PopplerDest *dest)
788 {
789         EvLinkDest *ev_dest = NULL;
790         const char *unimplemented_dest = NULL;
791
792         g_assert (dest != NULL);
793
794         switch (dest->type) {
795                 case POPPLER_DEST_XYZ: {
796                         PopplerPage *poppler_page;
797                         double height;
798
799                         poppler_page = poppler_document_get_page (pdf_document->document,
800                                                                   MAX (0, dest->page_num - 1));
801                         poppler_page_get_size (poppler_page, NULL, &height);
802                         ev_dest = ev_link_dest_new_xyz (dest->page_num - 1,
803                                                         dest->left,
804                                                         height - dest->top,
805                                                         dest->zoom);
806                         g_object_unref (poppler_page);
807                 }
808                         break;
809                 case POPPLER_DEST_FIT:
810                         ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
811                         break;
812                 case POPPLER_DEST_FITH: {
813                         PopplerPage *poppler_page;
814                         double height;
815
816                         poppler_page = poppler_document_get_page (pdf_document->document,
817                                                                   MAX (0, dest->page_num - 1));
818                         poppler_page_get_size (poppler_page, NULL, &height);
819                         ev_dest = ev_link_dest_new_fith (dest->page_num - 1,
820                                                          height - dest->top);
821                         g_object_unref (poppler_page);
822                 }
823                         break;
824                 case POPPLER_DEST_FITV:
825                         ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
826                                                          dest->left);
827                         break;
828                 case POPPLER_DEST_FITR: {
829                         PopplerPage *poppler_page;
830                         double height;
831
832                         poppler_page = poppler_document_get_page (pdf_document->document,
833                                                                   MAX (0, dest->page_num - 1));
834                         poppler_page_get_size (poppler_page, NULL, &height);
835                         ev_dest = ev_link_dest_new_fitr (dest->page_num - 1,
836                                                          dest->left,
837                                                          height - dest->bottom,
838                                                          dest->right,
839                                                          height - dest->top);
840                         g_object_unref (poppler_page);
841                 }
842                         break;
843                 case POPPLER_DEST_FITB:
844                         unimplemented_dest = "POPPLER_DEST_FITB";
845                         break;
846                 case POPPLER_DEST_FITBH:
847                         unimplemented_dest = "POPPLER_DEST_FITBH";
848                         break;
849                 case POPPLER_DEST_FITBV:
850                         unimplemented_dest = "POPPLER_DEST_FITBV";
851                         break;
852                 case POPPLER_DEST_NAMED:
853                         ev_dest = ev_link_dest_new_named (dest->named_dest);
854                         break;
855                 case POPPLER_DEST_UNKNOWN:
856                         unimplemented_dest = "POPPLER_DEST_UNKNOWN";
857                         break;
858         }
859
860         if (unimplemented_dest) {
861                 g_warning ("Unimplemented named action: %s, please post a "
862                            "bug report in Evince bugzilla "
863                            "(http://bugzilla.gnome.org) with a testcase.",
864                            unimplemented_dest);
865         }
866
867         if (!ev_dest)
868                 ev_dest = ev_link_dest_new_page (dest->page_num - 1);
869         
870         return ev_dest;
871 }
872
873 static EvLink *
874 ev_link_from_action (PdfDocument   *pdf_document,
875                      PopplerAction *action)
876 {
877         EvLink       *link = NULL;
878         EvLinkAction *ev_action = NULL;
879         const char   *unimplemented_action = NULL;
880
881         switch (action->type) {
882                 case POPPLER_ACTION_GOTO_DEST: {
883                         EvLinkDest *dest;
884                         
885                         dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest);
886                         ev_action = ev_link_action_new_dest (dest);
887                 }
888                         break;
889                 case POPPLER_ACTION_GOTO_REMOTE: {
890                         EvLinkDest *dest;
891                         
892                         dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest);
893                         ev_action = ev_link_action_new_remote (dest, 
894                                                                action->goto_remote.file_name);
895                         
896                 }
897                         break;
898                 case POPPLER_ACTION_LAUNCH:
899                         ev_action = ev_link_action_new_launch (action->launch.file_name,
900                                                                action->launch.params);
901                         break;
902                 case POPPLER_ACTION_URI:
903                         ev_action = ev_link_action_new_external_uri (action->uri.uri);
904                         break;
905                 case POPPLER_ACTION_NAMED:
906                         ev_action = ev_link_action_new_named (action->named.named_dest);
907                         break;
908                 case POPPLER_ACTION_MOVIE:
909                         unimplemented_action = "POPPLER_ACTION_MOVIE";
910                         break;
911                 case POPPLER_ACTION_UNKNOWN:
912                         unimplemented_action = "POPPLER_ACTION_UNKNOWN";
913         }
914         
915         if (unimplemented_action) {
916                 g_warning ("Unimplemented action: %s, please post a bug report with a testcase.",
917                            unimplemented_action);
918         }
919         
920         link = ev_link_new (action->any.title, ev_action);
921         
922         return link;    
923 }
924
925 static void
926 build_tree (PdfDocument      *pdf_document,
927             GtkTreeModel     *model,
928             GtkTreeIter      *parent,
929             PopplerIndexIter *iter)
930 {
931         
932         do {
933                 GtkTreeIter tree_iter;
934                 PopplerIndexIter *child;
935                 PopplerAction *action;
936                 EvLink *link = NULL;
937                 gboolean expand;
938                 char *title_markup;
939                 
940                 action = poppler_index_iter_get_action (iter);
941                 expand = poppler_index_iter_is_open (iter);
942
943                 if (!action)
944                         continue;
945
946                 switch (action->type) {
947                         case POPPLER_ACTION_GOTO_DEST: {
948                                 /* For bookmarks, solve named destinations */
949                                 if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
950                                         PopplerDest *dest;
951                                         EvLinkDest *ev_dest = NULL;
952                                         EvLinkAction *ev_action;
953                                         
954                                         dest = poppler_document_find_dest (pdf_document->document,
955                                                                            action->goto_dest.dest->named_dest);
956                                         if (!dest) {
957                                                 link = ev_link_from_action (pdf_document, action);
958                                                 break;
959                                         }
960                                         
961                                         ev_dest = ev_link_dest_from_dest (pdf_document, dest);
962                                         poppler_dest_free (dest);
963                                         
964                                         ev_action = ev_link_action_new_dest (ev_dest);
965                                         link = ev_link_new (action->any.title, ev_action);
966                                 } else {
967                                         link = ev_link_from_action (pdf_document, action);
968                                 }
969                         }
970                                 break;
971                         default:
972                                 link = ev_link_from_action (pdf_document, action);
973                                 break;
974                 }
975                 
976                 if (!link) {
977                         poppler_action_free (action);
978                         continue;
979                 }
980
981                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
982                 title_markup = g_markup_escape_text (ev_link_get_title (link), -1);
983                 
984                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
985                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
986                                     EV_DOCUMENT_LINKS_COLUMN_LINK, link,
987                                     EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
988                                     -1);
989                 
990                 g_free (title_markup);
991                 g_object_unref (link);
992                 
993                 child = poppler_index_iter_get_child (iter);
994                 if (child)
995                         build_tree (pdf_document, model, &tree_iter, child);
996                 poppler_index_iter_free (child);
997                 poppler_action_free (action);
998                 
999         } while (poppler_index_iter_next (iter));
1000 }
1001
1002 static GtkTreeModel *
1003 pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1004 {
1005         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1006         GtkTreeModel *model = NULL;
1007         PopplerIndexIter *iter;
1008         
1009         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1010
1011         iter = poppler_index_iter_new (pdf_document->document);
1012         /* Create the model if we have items*/
1013         if (iter != NULL) {
1014                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1015                                                              G_TYPE_STRING,
1016                                                              G_TYPE_OBJECT,
1017                                                              G_TYPE_BOOLEAN);
1018                 build_tree (pdf_document, model, NULL, iter);
1019                 poppler_index_iter_free (iter);
1020         }
1021         
1022         return model;
1023 }
1024
1025 static GList *
1026 pdf_document_links_get_links (EvDocumentLinks *document_links,
1027                               gint             page)
1028 {
1029         PdfDocument *pdf_document;
1030         PopplerPage *poppler_page;
1031         GList *retval = NULL;
1032         GList *mapping_list;
1033         GList *list;
1034         double height;
1035
1036         pdf_document = PDF_DOCUMENT (document_links);
1037         poppler_page = poppler_document_get_page (pdf_document->document,
1038                                                   page);
1039         mapping_list = poppler_page_get_link_mapping (poppler_page);
1040         poppler_page_get_size (poppler_page, NULL, &height);
1041
1042         for (list = mapping_list; list; list = list->next) {
1043                 PopplerLinkMapping *link_mapping;
1044                 EvLinkMapping *ev_link_mapping;
1045
1046                 link_mapping = (PopplerLinkMapping *)list->data;
1047                 ev_link_mapping = g_new (EvLinkMapping, 1);
1048                 ev_link_mapping->link = ev_link_from_action (pdf_document,
1049                                                              link_mapping->action);
1050                 ev_link_mapping->x1 = link_mapping->area.x1;
1051                 ev_link_mapping->x2 = link_mapping->area.x2;
1052                 /* Invert this for X-style coordinates */
1053                 ev_link_mapping->y1 = height - link_mapping->area.y2;
1054                 ev_link_mapping->y2 = height - link_mapping->area.y1;
1055
1056                 retval = g_list_prepend (retval, ev_link_mapping);
1057         }
1058
1059         poppler_page_free_link_mapping (mapping_list);
1060         g_object_unref (poppler_page);
1061
1062         return g_list_reverse (retval);
1063 }
1064
1065 static EvLinkDest *
1066 pdf_document_links_find_link_dest (EvDocumentLinks  *document_links,
1067                                    const gchar      *link_name)
1068 {
1069         PdfDocument *pdf_document;
1070         PopplerDest *dest;
1071         EvLinkDest *ev_dest = NULL;
1072
1073         pdf_document = PDF_DOCUMENT (document_links);
1074         dest = poppler_document_find_dest (pdf_document->document,
1075                                            link_name);
1076         if (dest) {
1077                 ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1078                 poppler_dest_free (dest);
1079         }
1080
1081         return ev_dest;
1082 }
1083
1084 static void
1085 pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
1086 {
1087         iface->has_document_links = pdf_document_links_has_document_links;
1088         iface->get_links_model = pdf_document_links_get_links_model;
1089         iface->get_links = pdf_document_links_get_links;
1090         iface->find_link_dest = pdf_document_links_find_link_dest;
1091 }
1092
1093 static GdkPixbuf *
1094 make_thumbnail_for_size (PdfDocument   *pdf_document,
1095                          gint           page,
1096                          int            rotation,
1097                          gint           size)
1098 {
1099         PopplerPage *poppler_page;
1100         GdkPixbuf *pixbuf;
1101         int width, height;
1102         double scale;
1103         gdouble unscaled_width, unscaled_height;
1104
1105         poppler_page = poppler_document_get_page (pdf_document->document, page);
1106         g_return_val_if_fail (poppler_page != NULL, NULL);
1107
1108         pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document), page,
1109                                                 size, &width, &height);
1110         poppler_page_get_size (poppler_page, &unscaled_width, &unscaled_height);
1111         scale = width / unscaled_width;
1112
1113         /* rotate */
1114         if (rotation == 90 || rotation == 270) {
1115                 int temp;
1116                 temp = width;
1117                 width = height;
1118                 height = temp;
1119         }
1120
1121         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
1122                                  width, height);
1123         gdk_pixbuf_fill (pixbuf, 0xffffffff);
1124
1125         poppler_page_render_to_pixbuf (poppler_page, 0, 0,
1126                                        width, height,
1127                                        scale, rotation, pixbuf);
1128        
1129
1130         g_object_unref (poppler_page);
1131
1132         return pixbuf;
1133 }
1134
1135 static GdkPixbuf *
1136 pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
1137                                        gint                  page,
1138                                        gint                  rotation,
1139                                        gint                  size,
1140                                        gboolean              border)
1141 {
1142         PdfDocument *pdf_document;
1143         PopplerPage *poppler_page;
1144         GdkPixbuf *pixbuf;
1145         GdkPixbuf *border_pixbuf;
1146
1147         pdf_document = PDF_DOCUMENT (document_thumbnails);
1148
1149         poppler_page = poppler_document_get_page (pdf_document->document, page);
1150         g_return_val_if_fail (poppler_page != NULL, NULL);
1151
1152         pixbuf = poppler_page_get_thumbnail (poppler_page);
1153         
1154         if (pixbuf == NULL) {
1155                 /* There is no provided thumbnail.  We need to make one. */
1156                 pixbuf = make_thumbnail_for_size (pdf_document, page, rotation, size);
1157         }
1158
1159         if (border) {           
1160                 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, rotation, pixbuf);
1161                 g_object_unref (pixbuf);
1162                 pixbuf = border_pixbuf;
1163         }               
1164
1165         g_object_unref (poppler_page);
1166         
1167         return pixbuf;
1168 }
1169
1170 static void
1171 pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
1172                                         gint                  page,
1173                                         gint                  size,
1174                                         gint                 *width,
1175                                         gint                 *height)
1176 {
1177         PdfDocument *pdf_document;
1178         PopplerPage *poppler_page;
1179         gint has_thumb;
1180         
1181         pdf_document = PDF_DOCUMENT (document_thumbnails);
1182         poppler_page = poppler_document_get_page (pdf_document->document, page);
1183
1184         g_return_if_fail (width != NULL);
1185         g_return_if_fail (height != NULL);
1186         g_return_if_fail (poppler_page != NULL);
1187
1188         has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
1189
1190         if (!has_thumb) {
1191                 double page_width, page_height;
1192
1193                 poppler_page_get_size (poppler_page, &page_width, &page_height);
1194                 *width = size;
1195                 *height = (int) (size * page_height / page_width);
1196         }
1197         g_object_unref (poppler_page);
1198 }
1199
1200 static void
1201 pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
1202 {
1203         iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
1204         iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
1205 }
1206
1207
1208 static gboolean
1209 pdf_document_search_idle_callback (void *data)
1210 {
1211         PdfDocumentSearch *search = (PdfDocumentSearch*) data;
1212         PdfDocument *pdf_document = search->document;
1213         int n_pages;
1214         GList *matches;
1215         PopplerPage *page;
1216
1217         page = poppler_document_get_page (search->document->document,
1218                                           search->search_page);
1219
1220         ev_document_doc_mutex_lock ();
1221         matches = poppler_page_find_text (page, search->text);
1222         ev_document_doc_mutex_unlock ();
1223
1224         g_object_unref (page);
1225
1226         search->pages[search->search_page] = matches;
1227         ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
1228                                   search->search_page);
1229
1230         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
1231         search->search_page += 1;
1232         if (search->search_page == n_pages) {
1233                 /* wrap around */
1234                 search->search_page = 0;
1235         }
1236
1237         if (search->search_page != search->start_page) {
1238                 return TRUE;
1239         }
1240
1241         /* We're done. */
1242         search->idle = 0; /* will return FALSE to remove */
1243         return FALSE;
1244 }
1245
1246
1247 static PdfDocumentSearch *
1248 pdf_document_search_new (PdfDocument *pdf_document,
1249                          int          start_page,
1250                          const char  *text)
1251 {
1252         PdfDocumentSearch *search;
1253         int n_pages;
1254         int i;
1255
1256         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
1257
1258         search = g_new0 (PdfDocumentSearch, 1);
1259
1260         search->text = g_strdup (text);
1261         search->pages = g_new0 (GList *, n_pages);
1262         for (i = 0; i < n_pages; i++) {
1263                 search->pages[i] = NULL;
1264         }
1265
1266         search->document = pdf_document;
1267
1268         /* We add at low priority so the progress bar repaints */
1269         search->idle = g_idle_add_full (G_PRIORITY_LOW,
1270                                         pdf_document_search_idle_callback,
1271                                         search,
1272                                         NULL);
1273
1274         search->start_page = start_page;
1275         search->search_page = start_page;
1276
1277         return search;
1278 }
1279
1280 static void
1281 pdf_document_find_begin (EvDocumentFind   *document,
1282                          int               page,
1283                          const char       *search_string,
1284                          gboolean          case_sensitive)
1285 {
1286         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1287
1288         /* FIXME handle case_sensitive (right now XPDF
1289          * code is always case insensitive for ASCII
1290          * and case sensitive for all other languaages)
1291          */
1292
1293         if (pdf_document->search &&
1294             strcmp (search_string, pdf_document->search->text) == 0)
1295                 return;
1296
1297         if (pdf_document->search)
1298                 pdf_document_search_free (pdf_document->search);
1299
1300         pdf_document->search = pdf_document_search_new (pdf_document,
1301                                                         page,
1302                                                         search_string);
1303 }
1304
1305 int
1306 pdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
1307 {
1308         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1309
1310         if (search) {
1311                 return g_list_length (search->pages[page]);
1312         } else {
1313                 return 0;
1314         }
1315 }
1316
1317 gboolean
1318 pdf_document_find_get_result (EvDocumentFind *document_find,
1319                               int             page,
1320                               int             n_result,
1321                               EvRectangle    *rectangle)
1322 {
1323         PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
1324         PdfDocumentSearch *search = pdf_document->search;
1325         PopplerPage *poppler_page;
1326         PopplerRectangle *r;
1327         double height;
1328
1329         if (search == NULL)
1330                 return FALSE;
1331
1332         r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
1333                                                   n_result);
1334         if (r == NULL)
1335                 return FALSE;
1336
1337         poppler_page = poppler_document_get_page (pdf_document->document, page);
1338         poppler_page_get_size (poppler_page, NULL, &height);
1339         rectangle->x1 = r->x1;
1340         rectangle->y1 = height - r->y2;
1341         rectangle->x2 = r->x2;
1342         rectangle->y2 = height - r->y1;
1343         g_object_unref (poppler_page);
1344                 
1345         return TRUE;
1346 }
1347
1348 int
1349 pdf_document_find_page_has_results (EvDocumentFind *document_find,
1350                                     int             page)
1351 {
1352         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1353
1354         return search && search->pages[page] != NULL;
1355 }
1356
1357 double
1358 pdf_document_find_get_progress (EvDocumentFind *document_find)
1359 {
1360         PdfDocumentSearch *search;
1361         int n_pages, pages_done;
1362
1363         search = PDF_DOCUMENT (document_find)->search;
1364
1365         if (search == NULL) {
1366                 return 0;
1367         }
1368
1369         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
1370         if (search->search_page > search->start_page) {
1371                 pages_done = search->search_page - search->start_page + 1;
1372         } else if (search->search_page == search->start_page) {
1373                 pages_done = n_pages;
1374         } else {
1375                 pages_done = n_pages - search->start_page + search->search_page;
1376         }
1377
1378         return pages_done / (double) n_pages;
1379 }
1380
1381 static void
1382 pdf_document_find_cancel (EvDocumentFind *document)
1383 {
1384         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1385
1386         if (pdf_document->search) {
1387                 pdf_document_search_free (pdf_document->search);
1388                 pdf_document->search = NULL;
1389         }
1390 }
1391
1392 static void
1393 pdf_document_find_iface_init (EvDocumentFindIface *iface)
1394 {
1395         iface->begin = pdf_document_find_begin;
1396         iface->get_n_results = pdf_document_find_get_n_results;
1397         iface->get_result = pdf_document_find_get_result;
1398         iface->page_has_results = pdf_document_find_page_has_results;
1399         iface->get_progress = pdf_document_find_get_progress;
1400         iface->cancel = pdf_document_find_cancel;
1401 }
1402
1403 static void
1404 pdf_document_ps_exporter_begin (EvPSExporter *exporter, const char *filename,
1405                                 int first_page, int last_page,
1406                                 double width, double height, gboolean duplex)
1407 {
1408         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1409         
1410         pdf_document->ps_file = poppler_ps_file_new (pdf_document->document, filename,
1411                                                      first_page,
1412                                                      last_page - first_page + 1);
1413         poppler_ps_file_set_paper_size (pdf_document->ps_file, width, height);
1414         poppler_ps_file_set_duplex (pdf_document->ps_file, duplex);
1415 }
1416
1417 static void
1418 pdf_document_ps_exporter_do_page (EvPSExporter *exporter, EvRenderContext *rc)
1419 {
1420         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1421         PopplerPage *poppler_page;
1422
1423         g_return_if_fail (pdf_document->ps_file != NULL);
1424
1425         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1426         poppler_page_render_to_ps (poppler_page, pdf_document->ps_file);
1427         g_object_unref (poppler_page);
1428 }
1429
1430 static void
1431 pdf_document_ps_exporter_end (EvPSExporter *exporter)
1432 {
1433         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1434
1435         poppler_ps_file_free (pdf_document->ps_file);
1436         pdf_document->ps_file = NULL;
1437 }
1438
1439 static void
1440 pdf_document_ps_exporter_iface_init (EvPSExporterIface *iface)
1441 {
1442         iface->begin = pdf_document_ps_exporter_begin;
1443         iface->do_page = pdf_document_ps_exporter_do_page;
1444         iface->end = pdf_document_ps_exporter_end;
1445 }
1446
1447
1448 void
1449 pdf_selection_render_selection (EvSelection      *selection,
1450                                 EvRenderContext  *rc,
1451                                 GdkPixbuf       **pixbuf,
1452                                 EvRectangle      *points,
1453                                 EvRectangle      *old_points,
1454                                 GdkColor        *text,
1455                                 GdkColor        *base)
1456 {
1457         PdfDocument *pdf_document;
1458         double width_points, height_points;
1459         gint width, height;
1460
1461         pdf_document = PDF_DOCUMENT (selection);
1462         set_rc_data (pdf_document, rc);
1463
1464         poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
1465         width = (int) ((width_points * rc->scale) + 0.5);
1466         height = (int) ((height_points * rc->scale) + 0.5);
1467
1468         if (*pixbuf == NULL) {
1469                 * pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
1470                                            TRUE, 8,
1471                                            width, height);
1472         }
1473         
1474         poppler_page_render_selection (POPPLER_PAGE (rc->data),
1475                                        rc->scale, rc->rotation, *pixbuf,
1476                                        (PopplerRectangle *)points,
1477                                        (PopplerRectangle *)old_points,
1478                                        text,
1479                                        base);
1480 }
1481
1482
1483 GdkRegion *
1484 pdf_selection_get_selection_region (EvSelection     *selection,
1485                                     EvRenderContext *rc,
1486                                     EvRectangle     *points)
1487 {
1488         PdfDocument *pdf_document;
1489         GdkRegion *retval;
1490
1491         pdf_document = PDF_DOCUMENT (selection);
1492
1493         set_rc_data (pdf_document, rc);
1494
1495         retval = poppler_page_get_selection_region ((PopplerPage *)rc->data, rc->scale, (PopplerRectangle *) points);
1496
1497         return retval;
1498 }
1499
1500 GdkRegion *
1501 pdf_selection_get_selection_map (EvSelection     *selection,
1502                                  EvRenderContext *rc)
1503 {
1504         PdfDocument *pdf_document;
1505         PopplerPage *poppler_page;
1506         PopplerRectangle points;
1507         GdkRegion *retval;
1508
1509         pdf_document = PDF_DOCUMENT (selection);
1510         poppler_page = poppler_document_get_page (pdf_document->document,
1511                                                   rc->page);
1512
1513         points.x1 = 0.0;
1514         points.y1 = 0.0;
1515         poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
1516         retval = poppler_page_get_selection_region (poppler_page, 1.0, &points);
1517         g_object_unref (poppler_page);
1518
1519         return retval;
1520 }
1521
1522 static void
1523 pdf_selection_iface_init (EvSelectionIface *iface)
1524 {
1525         iface->render_selection = pdf_selection_render_selection;
1526         iface->get_selection_region = pdf_selection_get_selection_region;
1527         iface->get_selection_map = pdf_selection_get_selection_map;
1528 }
1529
1530 PdfDocument *
1531 pdf_document_new (void)
1532 {
1533         return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
1534 }