~ubuntu-branches/ubuntu/trusty/evince/trusty-updates

« back to all changes in this revision

Viewing changes to .pc/git_correct_page_info.patch/backend/pdf/ev-poppler.cc

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2013-11-12 12:10:03 UTC
  • mfrom: (1.8.6)
  • Revision ID: package-import@ubuntu.com-20131112121003-cjura8gxxx9w2u7l
Tags: 3.10.2-0ubuntu1
* New upstream version
* debian/patches/git_give_focus_correctly.patch,
  debian/patches/git_correct_page_info.patch,
  debian/patches/git_djvu_segfault.patch:
  - dropped, those changes are in the new version

Show diffs side-by-side

added added

removed removed

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