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
4
* Copyright (C) 2009, Juanjo Marín <juanj.marin@juntadeandalucia.es>
5
* Copyright (C) 2004, Red Hat, Inc.
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)
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.
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.
28
#include <poppler-document.h>
29
#include <poppler-page.h>
31
#include <cairo-pdf.h>
36
#include <glib/gi18n-lib.h>
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"
58
#include <libxml/tree.h>
59
#include <libxml/parser.h>
60
#include <libxml/xpath.h>
61
#include <libxml/xpathInternals.h>
63
#if (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS))
64
#define HAVE_CAIRO_PRINT
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"
75
EvFileExporterFormat format;
85
#ifdef HAVE_CAIRO_PRINT
88
PopplerPSFile *ps_file;
92
struct _PdfDocumentClass
94
EvDocumentClass parent_class;
99
EvDocument parent_instance;
101
PopplerDocument *document;
103
gboolean forms_modified;
104
gboolean annots_modified;
106
PopplerFontInfo *font_info;
107
PopplerFontsIter *fonts_iter;
108
int fonts_scanned_pages;
109
gboolean missing_fonts;
111
PdfPrintContext *print_ctx;
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);
132
static EvLinkDest *ev_link_dest_from_dest (PdfDocument *pdf_document,
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,
142
EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document,
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);
175
pdf_document_dispose (GObject *object)
177
PdfDocument *pdf_document = PDF_DOCUMENT(object);
179
if (pdf_document->print_ctx) {
180
pdf_print_context_free (pdf_document->print_ctx);
181
pdf_document->print_ctx = NULL;
184
if (pdf_document->annots) {
185
g_hash_table_destroy (pdf_document->annots);
186
pdf_document->annots = NULL;
189
if (pdf_document->document) {
190
g_object_unref (pdf_document->document);
193
if (pdf_document->font_info) {
194
poppler_font_info_free (pdf_document->font_info);
197
if (pdf_document->fonts_iter) {
198
poppler_fonts_iter_free (pdf_document->fonts_iter);
201
G_OBJECT_CLASS (pdf_document_parent_class)->dispose (object);
205
pdf_document_init (PdfDocument *pdf_document)
207
pdf_document->password = NULL;
211
convert_error (GError *poppler_error,
214
if (poppler_error == NULL)
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;
225
g_set_error_literal (error,
228
poppler_error->message);
230
g_error_free (poppler_error);
232
g_propagate_error (error, poppler_error);
239
pdf_document_save (EvDocument *document,
243
PdfDocument *pdf_document = PDF_DOCUMENT (document);
245
GError *poppler_error = NULL;
247
if (pdf_document->forms_modified || pdf_document->annots_modified) {
248
retval = poppler_document_save (pdf_document->document,
249
uri, &poppler_error);
251
pdf_document->forms_modified = FALSE;
252
pdf_document->annots_modified = FALSE;
255
retval = poppler_document_save_a_copy (pdf_document->document,
256
uri, &poppler_error);
260
convert_error (poppler_error, error);
266
pdf_document_load (EvDocument *document,
270
GError *poppler_error = NULL;
271
PdfDocument *pdf_document = PDF_DOCUMENT (document);
273
pdf_document->document =
274
poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
276
if (pdf_document->document == NULL) {
277
convert_error (poppler_error, error);
285
pdf_document_load_stream (EvDocument *document,
286
GInputStream *stream,
287
EvDocumentLoadFlags flags,
288
GCancellable *cancellable,
292
PdfDocument *pdf_document = PDF_DOCUMENT (document);
294
pdf_document->document =
295
poppler_document_new_from_stream (stream, -1,
296
pdf_document->password,
300
if (pdf_document->document == NULL) {
301
convert_error (err, error);
309
pdf_document_load_gfile (EvDocument *document,
311
EvDocumentLoadFlags flags,
312
GCancellable *cancellable,
316
PdfDocument *pdf_document = PDF_DOCUMENT (document);
318
pdf_document->document =
319
poppler_document_new_from_gfile (file,
320
pdf_document->password,
324
if (pdf_document->document == NULL) {
325
convert_error (err, error);
333
pdf_document_get_n_pages (EvDocument *document)
335
return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
339
pdf_document_get_page (EvDocument *document,
342
PdfDocument *pdf_document = PDF_DOCUMENT (document);
343
PopplerPage *poppler_page;
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);
356
pdf_document_get_page_size (EvDocument *document,
361
g_return_if_fail (POPPLER_IS_PAGE (page->backend_page));
363
poppler_page_get_size (POPPLER_PAGE (page->backend_page), width, height);
367
pdf_document_get_page_label (EvDocument *document,
372
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
374
g_object_get (G_OBJECT (page->backend_page),
380
static cairo_surface_t *
381
pdf_page_render (PopplerPage *page,
386
cairo_surface_t *surface;
389
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
391
cr = cairo_create (surface);
393
switch (rc->rotation) {
395
cairo_translate (cr, width, 0);
398
cairo_translate (cr, width, height);
401
cairo_translate (cr, 0, height);
404
cairo_translate (cr, 0, 0);
406
cairo_scale (cr, rc->scale, rc->scale);
407
cairo_rotate (cr, rc->rotation * G_PI / 180.0);
408
poppler_page_render (page, cr);
410
cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
411
cairo_set_source_rgb (cr, 1., 1., 1.);
419
static cairo_surface_t *
420
pdf_document_render (EvDocument *document,
423
PopplerPage *poppler_page;
424
double width_points, height_points;
427
poppler_page = POPPLER_PAGE (rc->page->backend_page);
429
poppler_page_get_size (poppler_page,
430
&width_points, &height_points);
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);
436
width = (int) ((width_points * rc->scale) + 0.5);
437
height = (int) ((height_points * rc->scale) + 0.5);
440
return pdf_page_render (poppler_page,
445
make_thumbnail_for_page (PopplerPage *poppler_page,
451
cairo_surface_t *surface;
453
ev_document_fc_mutex_lock ();
454
surface = pdf_page_render (poppler_page, width, height, rc);
455
ev_document_fc_mutex_unlock ();
457
pixbuf = ev_document_misc_pixbuf_from_surface (surface);
458
cairo_surface_destroy (surface);
464
pdf_document_get_thumbnail (EvDocument *document,
467
PopplerPage *poppler_page;
468
cairo_surface_t *surface;
469
GdkPixbuf *pixbuf = NULL;
470
double page_width, page_height;
473
poppler_page = POPPLER_PAGE (rc->page->backend_page);
475
poppler_page_get_size (poppler_page,
476
&page_width, &page_height);
478
width = MAX ((gint)(page_width * rc->scale + 0.5), 1);
479
height = MAX ((gint)(page_height * rc->scale + 0.5), 1);
481
if (rc->rotation == 90 || rc->rotation == 270) {
489
surface = poppler_page_get_thumbnail (poppler_page);
491
pixbuf = ev_document_misc_pixbuf_from_surface (surface);
492
cairo_surface_destroy (surface);
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);
500
if (thumb_width == width) {
501
GdkPixbuf *rotated_pixbuf;
503
rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
504
(GdkPixbufRotation) (360 - rc->rotation));
505
g_object_unref (pixbuf);
506
pixbuf = rotated_pixbuf;
508
/* The provided thumbnail has a different size */
509
g_object_unref (pixbuf);
510
pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height);
513
/* There is no provided thumbnail. We need to make one. */
514
pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height);
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 */
523
pdf_document_get_format_from_metadata (xmlDocPtr doc,
524
xmlXPathContextPtr xpathCtx)
526
xmlXPathObjectPtr xpathObj;
527
xmlChar *part = NULL;
528
xmlChar *conf = NULL;
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/");
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]);
544
xmlXPathFreeObject (xpathObj);
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]);
553
xmlXPathFreeObject (xpathObj);
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]);
564
xmlXPathFreeObject (xpathObj);
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]);
573
xmlXPathFreeObject (xpathObj);
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]);
583
result = g_strdup_printf ("PDF/A - %s%s", part, conf);
593
static EvDocumentLicense *
594
pdf_document_get_license_from_metadata (xmlDocPtr doc,
595
xmlXPathContextPtr xpathCtx)
597
xmlXPathObjectPtr xpathObj;
598
xmlChar *marked = NULL;
599
const char *language_string;
602
gchar *tag, *tag_aux;
604
EvDocumentLicense *license;
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#");
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);
625
/* a) Not marked => No XMP Rights information */
631
license = ev_document_license_new ();
633
/* b) Marked False => Public Domain, no copyrighted material and no
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 */
639
/* Checking usage terms as defined by the XMP Rights Management
640
* Schema. This field is recomended to be checked by Creative
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]);
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);
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);
679
/* Checking the license URI as defined by the Creative Commons
680
* Schema. This field is recomended to be checked by Creative
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);
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);
704
if (!license->text && !license->uri && !license->web_statement) {
705
ev_document_license_free (license);
713
pdf_document_parse_metadata (const gchar *metadata,
714
EvDocumentInfo *info)
717
xmlXPathContextPtr xpathCtx;
720
doc = xmlParseMemory (metadata, strlen (metadata));
722
return; /* invalid xml metadata */
724
xpathCtx = xmlXPathNewContext (doc);
725
if (xpathCtx == NULL) {
727
return; /* invalid xpath context */
730
fmt = pdf_document_get_format_from_metadata (doc, xpathCtx);
732
g_free (info->format);
736
info->license = pdf_document_get_license_from_metadata (doc, xpathCtx);
738
xmlXPathFreeContext (xpathCtx);
743
static EvDocumentInfo *
744
pdf_document_get_info (EvDocument *document)
746
EvDocumentInfo *info;
747
PopplerPageLayout layout;
748
PopplerPageMode mode;
749
PopplerViewerPreferences view_prefs;
750
PopplerPermissions permissions;
754
info = g_new0 (EvDocumentInfo, 1);
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;
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),
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,
793
if (metadata != NULL) {
794
pdf_document_parse_metadata (metadata, info);
798
info->n_pages = ev_document_get_n_pages (document);
800
if (info->n_pages > 0) {
801
ev_document_get_page_size (document, 0,
802
&(info->paper_width),
803
&(info->paper_height));
805
info->paper_width = info->paper_width / 72.0f * 25.4f;
806
info->paper_height = info->paper_height / 72.0f * 25.4f;
810
case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
811
info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
813
case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
814
info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
816
case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
817
info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
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;
824
case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
825
info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
832
case POPPLER_PAGE_MODE_NONE:
833
info->mode = EV_DOCUMENT_MODE_NONE;
835
case POPPLER_PAGE_MODE_USE_THUMBS:
836
info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
838
case POPPLER_PAGE_MODE_USE_OC:
839
info->mode = EV_DOCUMENT_MODE_USE_OC;
841
case POPPLER_PAGE_MODE_FULL_SCREEN:
842
info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
844
case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
845
info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
851
if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
852
info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
854
if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
855
info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
857
if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
858
info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
860
if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
861
info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
863
if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
864
info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
866
if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
867
info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
869
if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
870
info->ui_hints |= EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
873
info->permissions = 0;
874
if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
875
info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
877
if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
878
info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
880
if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
881
info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
883
if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
884
info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
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"));
891
/* translators: this is the document security state */
892
info->security = g_strdup (_("No"));
895
info->linearized = linearized ? g_strdup (_("Yes")) : g_strdup (_("No"));
901
pdf_document_get_backend_info (EvDocument *document, EvDocumentBackendInfo *info)
903
PopplerBackend backend;
905
backend = poppler_get_backend ();
907
case POPPLER_BACKEND_CAIRO:
908
info->name = "poppler/cairo";
910
case POPPLER_BACKEND_SPLASH:
911
info->name = "poppler/splash";
914
info->name = "poppler/unknown";
918
info->version = poppler_get_version ();
924
pdf_document_support_synctex (EvDocument *document)
930
pdf_document_class_init (PdfDocumentClass *klass)
932
GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
933
EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass);
935
g_object_class->dispose = pdf_document_dispose;
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;
952
/* EvDocumentSecurity */
954
pdf_document_has_document_security (EvDocumentSecurity *document_security)
956
/* FIXME: do we really need to have this? */
961
pdf_document_set_password (EvDocumentSecurity *document_security,
962
const char *password)
964
PdfDocument *document = PDF_DOCUMENT (document_security);
966
if (document->password)
967
g_free (document->password);
969
document->password = g_strdup (password);
973
pdf_document_security_iface_init (EvDocumentSecurityInterface *iface)
975
iface->has_document_security = pdf_document_has_document_security;
976
iface->set_password = pdf_document_set_password;
980
pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
982
PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
985
n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
987
return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
991
pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
994
PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
997
g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
999
if (pdf_document->font_info == NULL) {
1000
pdf_document->font_info = poppler_font_info_new (pdf_document->document);
1003
if (pdf_document->fonts_iter) {
1004
poppler_fonts_iter_free (pdf_document->fonts_iter);
1007
pdf_document->fonts_scanned_pages += n_pages;
1009
result = poppler_font_info_scan (pdf_document->font_info, n_pages,
1010
&pdf_document->fonts_iter);
1012
pdf_document->fonts_scanned_pages = 0;
1013
poppler_font_info_free (pdf_document->font_info);
1014
pdf_document->font_info = NULL;
1021
font_type_to_string (PopplerFontType type)
1024
case POPPLER_FONT_TYPE_TYPE1:
1026
case POPPLER_FONT_TYPE_TYPE1C:
1027
return _("Type 1C");
1028
case POPPLER_FONT_TYPE_TYPE3:
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)");
1039
return _("Unknown font type");
1044
is_standard_font (const gchar *name, PopplerFontType type)
1046
/* list borrowed from Poppler: poppler/GfxFont.cc */
1047
static const char *base_14_subst_fonts[14] = {
1051
"Courier-BoldOblique",
1053
"Helvetica-Oblique",
1055
"Helvetica-BoldOblique",
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)
1070
for (i = 0; i < G_N_ELEMENTS (base_14_subst_fonts); i++) {
1071
if (g_str_equal (name, base_14_subst_fonts[i]))
1077
static const gchar *
1078
pdf_document_fonts_get_fonts_summary (EvDocumentFonts *document_fonts)
1080
PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
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 "
1088
return _("All fonts are either standard or embedded.");
1092
pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
1093
GtkTreeModel *model)
1095
PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
1096
PopplerFontsIter *iter = pdf_document->fonts_iter;
1098
g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
1104
GtkTreeIter list_iter;
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;
1117
name = poppler_fonts_iter_get_name (iter);
1120
name = _("No name");
1123
encoding = poppler_fonts_iter_get_encoding (iter);
1125
/* translators: When a font type does not have
1126
encoding information or it is unknown. Example:
1129
encoding = _("None");
1132
type = poppler_fonts_iter_get_font_type (iter);
1133
type_str = font_type_to_string (type);
1135
if (poppler_fonts_iter_is_embedded (iter)) {
1136
if (poppler_fonts_iter_is_subset (iter))
1137
embedded = _("Embedded subset");
1139
embedded = _("Embedded");
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
1146
* "Type 1 (One of the Standard 14 Fonts)"
1148
standard_str = _(" (One of the Standard 14 Fonts)");
1150
/* Translators: string starting with a space
1151
* because it is directly appended to the font
1153
* "TrueType (Not one of the Standard 14 Fonts)"
1155
standard_str = _(" (Not one of the Standard 14 Fonts)");
1156
pdf_document->missing_fonts = TRUE;
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");
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);
1171
details = g_markup_printf_escaped ("%s%s\n%s: %s\n%s",
1172
type_str, standard_str,
1173
encoding_text, encoding, embedded);
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,
1182
} while (poppler_fonts_iter_next (iter));
1186
pdf_document_document_fonts_iface_init (EvDocumentFontsInterface *iface)
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;
1195
pdf_document_links_has_document_links (EvDocumentLinks *document_links)
1197
PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1198
PopplerIndexIter *iter;
1200
g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
1202
iter = poppler_index_iter_new (pdf_document->document);
1205
poppler_index_iter_free (iter);
1211
ev_link_dest_from_dest (PdfDocument *pdf_document,
1214
EvLinkDest *ev_dest = NULL;
1215
const char *unimplemented_dest = NULL;
1217
g_assert (dest != NULL);
1219
switch (dest->type) {
1220
case POPPLER_DEST_XYZ: {
1221
PopplerPage *poppler_page;
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,
1229
height - MIN (height, dest->top),
1234
g_object_unref (poppler_page);
1237
case POPPLER_DEST_FITB:
1238
case POPPLER_DEST_FIT:
1239
ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
1241
case POPPLER_DEST_FITBH:
1242
case POPPLER_DEST_FITH: {
1243
PopplerPage *poppler_page;
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),
1252
g_object_unref (poppler_page);
1255
case POPPLER_DEST_FITBV:
1256
case POPPLER_DEST_FITV:
1257
ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
1261
case POPPLER_DEST_FITR: {
1262
PopplerPage *poppler_page;
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);
1278
case POPPLER_DEST_NAMED:
1279
ev_dest = ev_link_dest_new_named (dest->named_dest);
1281
case POPPLER_DEST_UNKNOWN:
1282
unimplemented_dest = "POPPLER_DEST_UNKNOWN";
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);
1294
ev_dest = ev_link_dest_new_page (dest->page_num - 1);
1300
ev_link_from_action (PdfDocument *pdf_document,
1301
PopplerAction *action)
1303
EvLink *link = NULL;
1304
EvLinkAction *ev_action = NULL;
1305
const char *unimplemented_action = NULL;
1307
switch (action->type) {
1308
case POPPLER_ACTION_NONE:
1310
case POPPLER_ACTION_GOTO_DEST: {
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);
1318
case POPPLER_ACTION_GOTO_REMOTE: {
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);
1328
case POPPLER_ACTION_LAUNCH:
1329
ev_action = ev_link_action_new_launch (action->launch.file_name,
1330
action->launch.params);
1332
case POPPLER_ACTION_URI:
1333
ev_action = ev_link_action_new_external_uri (action->uri.uri);
1335
case POPPLER_ACTION_NAMED:
1336
ev_action = ev_link_action_new_named (action->named.named_dest);
1338
case POPPLER_ACTION_MOVIE:
1339
unimplemented_action = "POPPLER_ACTION_MOVIE";
1341
case POPPLER_ACTION_RENDITION:
1342
unimplemented_action = "POPPLER_ACTION_RENDITION";
1344
case POPPLER_ACTION_OCG_STATE: {
1345
GList *on_list = NULL;
1346
GList *off_list = NULL;
1347
GList *toggle_list = NULL;
1350
for (l = action->ocg_state.state_list; l; l = g_list_next (l)) {
1351
PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data;
1353
for (m = action_layer->layers; m; m = g_list_next (m)) {
1354
PopplerLayer *layer = (PopplerLayer *)m->data;
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),
1361
g_object_ref (layer),
1362
(GDestroyNotify)g_object_unref);
1364
switch (action_layer->action) {
1365
case POPPLER_ACTION_LAYER_ON:
1366
on_list = g_list_prepend (on_list, ev_layer);
1368
case POPPLER_ACTION_LAYER_OFF:
1369
off_list = g_list_prepend (off_list, ev_layer);
1371
case POPPLER_ACTION_LAYER_TOGGLE:
1372
toggle_list = g_list_prepend (toggle_list, ev_layer);
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));
1386
case POPPLER_ACTION_JAVASCRIPT:
1387
unimplemented_action = "POPPLER_ACTION_JAVASCRIPT";
1389
case POPPLER_ACTION_UNKNOWN:
1390
unimplemented_action = "POPPLER_ACTION_UNKNOWN";
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);
1399
link = ev_link_new (action->any.title, ev_action);
1401
g_object_unref (ev_action);
1407
build_tree (PdfDocument *pdf_document,
1408
GtkTreeModel *model,
1409
GtkTreeIter *parent,
1410
PopplerIndexIter *iter)
1414
GtkTreeIter tree_iter;
1415
PopplerIndexIter *child;
1416
PopplerAction *action;
1417
EvLink *link = NULL;
1421
action = poppler_index_iter_get_action (iter);
1422
expand = poppler_index_iter_is_open (iter);
1427
link = ev_link_from_action (pdf_document, action);
1428
if (!link || strlen (ev_link_get_title (link)) <= 0) {
1429
poppler_action_free (action);
1431
g_object_unref (link);
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);
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,
1445
g_free (title_markup);
1446
g_object_unref (link);
1448
child = poppler_index_iter_get_child (iter);
1450
build_tree (pdf_document, model, &tree_iter, child);
1451
poppler_index_iter_free (child);
1452
poppler_action_free (action);
1454
} while (poppler_index_iter_next (iter));
1457
static GtkTreeModel *
1458
pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1460
PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1461
GtkTreeModel *model = NULL;
1462
PopplerIndexIter *iter;
1464
g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1466
iter = poppler_index_iter_new (pdf_document->document);
1467
/* Create the model if we have items*/
1469
model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1474
build_tree (pdf_document, model, NULL, iter);
1475
poppler_index_iter_free (iter);
1481
static EvMappingList *
1482
pdf_document_links_get_links (EvDocumentLinks *document_links,
1485
PdfDocument *pdf_document;
1486
PopplerPage *poppler_page;
1487
GList *retval = NULL;
1488
GList *mapping_list;
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);
1497
for (list = mapping_list; list; list = list->next) {
1498
PopplerLinkMapping *link_mapping;
1499
EvMapping *ev_link_mapping;
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;
1511
retval = g_list_prepend (retval, ev_link_mapping);
1514
poppler_page_free_link_mapping (mapping_list);
1516
return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref);
1520
pdf_document_links_find_link_dest (EvDocumentLinks *document_links,
1521
const gchar *link_name)
1523
PdfDocument *pdf_document;
1525
EvLinkDest *ev_dest = NULL;
1527
pdf_document = PDF_DOCUMENT (document_links);
1528
dest = poppler_document_find_dest (pdf_document->document,
1531
ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1532
poppler_dest_free (dest);
1539
pdf_document_links_find_link_page (EvDocumentLinks *document_links,
1540
const gchar *link_name)
1542
PdfDocument *pdf_document;
1546
pdf_document = PDF_DOCUMENT (document_links);
1547
dest = poppler_document_find_dest (pdf_document->document,
1550
retval = dest->page_num - 1;
1551
poppler_dest_free (dest);
1558
pdf_document_document_links_iface_init (EvDocumentLinksInterface *iface)
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;
1567
static EvMappingList *
1568
pdf_document_images_get_image_mapping (EvDocumentImages *document_images,
1571
GList *retval = NULL;
1572
PopplerPage *poppler_page;
1573
GList *mapping_list;
1576
poppler_page = POPPLER_PAGE (page->backend_page);
1577
mapping_list = poppler_page_get_image_mapping (poppler_page);
1579
for (list = mapping_list; list; list = list->next) {
1580
PopplerImageMapping *image_mapping;
1581
EvMapping *ev_image_mapping;
1583
image_mapping = (PopplerImageMapping *)list->data;
1585
ev_image_mapping = g_new (EvMapping, 1);
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;
1593
retval = g_list_prepend (retval, ev_image_mapping);
1596
poppler_page_free_image_mapping (mapping_list);
1598
return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref);
1602
pdf_document_images_get_image (EvDocumentImages *document_images,
1605
GdkPixbuf *retval = NULL;
1606
PdfDocument *pdf_document;
1607
PopplerPage *poppler_page;
1608
cairo_surface_t *surface;
1610
pdf_document = PDF_DOCUMENT (document_images);
1611
poppler_page = poppler_document_get_page (pdf_document->document,
1612
ev_image_get_page (image));
1614
surface = poppler_page_get_image (poppler_page, ev_image_get_id (image));
1616
retval = ev_document_misc_pixbuf_from_surface (surface);
1617
cairo_surface_destroy (surface);
1620
g_object_unref (poppler_page);
1626
pdf_document_document_images_iface_init (EvDocumentImagesInterface *iface)
1628
iface->get_image_mapping = pdf_document_images_get_image_mapping;
1629
iface->get_image = pdf_document_images_get_image;
1633
pdf_document_find_find_text_with_options (EvDocumentFind *document_find,
1636
EvFindOptions options)
1639
PopplerPage *poppler_page;
1641
GList *retval = NULL;
1642
guint find_flags = 0;
1644
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
1645
g_return_val_if_fail (text != NULL, NULL);
1647
poppler_page = POPPLER_PAGE (page->backend_page);
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);
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;
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;
1669
retval = g_list_prepend (retval, ev_rect);
1672
g_list_foreach (matches, (GFunc)poppler_rectangle_free, NULL);
1673
g_list_free (matches);
1675
return g_list_reverse (retval);
1679
pdf_document_find_find_text (EvDocumentFind *document_find,
1682
gboolean case_sensitive)
1687
options |= EV_FIND_CASE_SENSITIVE;
1689
return pdf_document_find_find_text_with_options (document_find, page, text, (EvFindOptions)options);
1692
static EvFindOptions
1693
pdf_document_find_get_supported_options (EvDocumentFind *document_find)
1695
return (EvFindOptions)(EV_FIND_CASE_SENSITIVE | EV_FIND_WHOLE_WORDS_ONLY);
1699
pdf_document_find_iface_init (EvDocumentFindInterface *iface)
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;
1707
pdf_print_context_free (PdfPrintContext *ctx)
1712
#ifdef HAVE_CAIRO_PRINT
1714
cairo_destroy (ctx->cr);
1719
poppler_ps_file_free (ctx->ps_file);
1720
ctx->ps_file = NULL;
1727
pdf_document_file_exporter_begin (EvFileExporter *exporter,
1728
EvFileExporterContext *fc)
1730
PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1731
PdfPrintContext *ctx;
1732
#ifdef HAVE_CAIRO_PRINT
1733
cairo_surface_t *surface = NULL;
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;
1742
#ifdef HAVE_CAIRO_PRINT
1743
ctx->pages_per_sheet = CLAMP (fc->pages_per_sheet, 1, 16);
1745
ctx->paper_width = fc->paper_width;
1746
ctx->paper_height = fc->paper_height;
1748
switch (fc->pages_per_sheet) {
1776
ctx->pages_printed = 0;
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);
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);
1790
g_assert_not_reached ();
1793
ctx->cr = cairo_create (surface);
1794
cairo_surface_destroy (surface);
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);
1804
#endif /* HAVE_CAIRO_PRINT */
1808
pdf_document_file_exporter_begin_page (EvFileExporter *exporter)
1810
PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1811
PdfPrintContext *ctx = pdf_document->print_ctx;
1813
g_return_if_fail (pdf_document->print_ctx != NULL);
1815
ctx->pages_printed = 0;
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),
1823
} else if (ctx->format == EV_FILE_FORMAT_PDF) {
1824
cairo_pdf_surface_set_size (cairo_get_target (ctx->cr),
1829
#endif /* HAVE_CAIRO_PRINT */
1833
pdf_document_file_exporter_do_page (EvFileExporter *exporter,
1834
EvRenderContext *rc)
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;
1843
gdouble width, height;
1844
gdouble pwidth, pheight;
1845
gdouble xscale, yscale;
1848
g_return_if_fail (pdf_document->print_ctx != NULL);
1850
poppler_page = POPPLER_PAGE (rc->page->backend_page);
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);
1857
if (page_width > page_height && page_width > ctx->paper_width) {
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;
1869
width = ctx->paper_width;
1870
height = ctx->paper_height;
1873
if (ctx->pages_per_sheet == 2 || ctx->pages_per_sheet == 6) {
1886
page_width = page_height;
1890
pwidth = width / ctx->pages_x;
1891
pheight = height / ctx->pages_y;
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;
1898
if (yscale < xscale) {
1905
xscale = yscale = 1;
1910
cairo_save (ctx->cr);
1912
cairo_matrix_t matrix;
1914
cairo_translate (ctx->cr, (2 * y + 1) * pwidth, 0);
1915
cairo_matrix_init (&matrix,
1919
cairo_transform (ctx->cr, &matrix);
1922
cairo_translate (ctx->cr,
1923
x * (rotate ? pheight : pwidth),
1924
y * (rotate ? pwidth : pheight));
1925
cairo_scale (ctx->cr, xscale, yscale);
1927
poppler_page_render_for_printing (poppler_page, ctx->cr);
1929
ctx->pages_printed++;
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 */
1939
pdf_document_file_exporter_end_page (EvFileExporter *exporter)
1941
PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1942
PdfPrintContext *ctx = pdf_document->print_ctx;
1944
g_return_if_fail (pdf_document->print_ctx != NULL);
1946
#ifdef HAVE_CAIRO_PRINT
1947
cairo_show_page (ctx->cr);
1952
pdf_document_file_exporter_end (EvFileExporter *exporter)
1954
PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1956
pdf_print_context_free (pdf_document->print_ctx);
1957
pdf_document->print_ctx = NULL;
1960
static EvFileExporterCapabilities
1961
pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
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 |
1973
#ifdef HAVE_CAIRO_PDF
1974
EV_FILE_EXPORTER_CAN_GENERATE_PDF |
1976
EV_FILE_EXPORTER_CAN_GENERATE_PS);
1980
pdf_document_file_exporter_iface_init (EvFileExporterInterface *iface)
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;
1990
/* EvDocumentPrint */
1992
pdf_document_print_print_page (EvDocumentPrint *document,
1996
poppler_page_render_for_printing (POPPLER_PAGE (page->backend_page), cr);
2000
pdf_document_document_print_iface_init (EvDocumentPrintInterface *iface)
2002
iface->print_page = pdf_document_print_print_page;
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,
2015
PopplerPage *poppler_page;
2017
PopplerColor text_color, base_color;
2018
double width_points, height_points;
2021
poppler_page = POPPLER_PAGE (rc->page->backend_page);
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);
2028
text_color.red = text->red;
2029
text_color.green = text->green;
2030
text_color.blue = text->blue;
2032
base_color.red = base->red;
2033
base_color.green = base->green;
2034
base_color.blue = base->blue;
2036
if (*surface == NULL) {
2037
*surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
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,
2050
(PopplerRectangle *)points,
2051
(PopplerRectangle *)old_points,
2052
(PopplerSelectionStyle)style,
2059
pdf_selection_get_selected_text (EvSelection *selection,
2061
EvSelectionStyle style,
2062
EvRectangle *points)
2064
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
2066
return poppler_page_get_selected_text (POPPLER_PAGE (page->backend_page),
2067
(PopplerSelectionStyle)style,
2068
(PopplerRectangle *)points);
2071
static cairo_region_t *
2072
create_region_from_poppler_region (GList *region, gdouble scale)
2075
cairo_region_t *retval;
2077
retval = cairo_region_create ();
2079
for (l = region; l; l = g_list_next (l)) {
2080
PopplerRectangle *rectangle;
2081
cairo_rectangle_int_t rect;
2083
rectangle = (PopplerRectangle *)l->data;
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);
2091
poppler_rectangle_free (rectangle);
2097
static cairo_region_t *
2098
pdf_selection_get_selection_region (EvSelection *selection,
2099
EvRenderContext *rc,
2100
EvSelectionStyle style,
2101
EvRectangle *points)
2103
PopplerPage *poppler_page;
2104
cairo_region_t *retval;
2107
poppler_page = POPPLER_PAGE (rc->page->backend_page);
2108
region = poppler_page_get_selection_region (poppler_page,
2110
(PopplerSelectionStyle)style,
2111
(PopplerRectangle *) points);
2112
retval = create_region_from_poppler_region (region, rc->scale);
2113
g_list_free (region);
2119
pdf_selection_iface_init (EvSelectionInterface *iface)
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;
2127
/* EvDocumentText */
2128
static cairo_region_t *
2129
pdf_document_text_get_text_mapping (EvDocumentText *document_text,
2132
PopplerPage *poppler_page;
2133
PopplerRectangle points;
2135
cairo_region_t *retval;
2137
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
2139
poppler_page = POPPLER_PAGE (page->backend_page);
2143
poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
2145
region = poppler_page_get_selection_region (poppler_page, 1.0,
2146
POPPLER_SELECTION_GLYPH,
2148
retval = create_region_from_poppler_region (region, 1.0);
2149
g_list_free (region);
2155
pdf_document_text_get_text (EvDocumentText *selection,
2158
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
2160
return poppler_page_get_text (POPPLER_PAGE (page->backend_page));
2164
pdf_document_text_get_text_layout (EvDocumentText *selection,
2166
EvRectangle **areas,
2169
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), FALSE);
2171
return poppler_page_get_text_layout (POPPLER_PAGE (page->backend_page),
2172
(PopplerRectangle **)areas, n_areas);
2175
static PangoAttrList *
2176
pdf_document_text_get_text_attrs (EvDocumentText *document_text,
2179
GList *backend_attrs_list, *l;
2180
PangoAttrList *attrs_list;
2182
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
2184
backend_attrs_list = poppler_page_get_text_attributes (POPPLER_PAGE (page->backend_page));
2185
if (!backend_attrs_list)
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;
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);
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);
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);
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);
2222
poppler_page_free_text_attributes (backend_attrs_list);
2228
pdf_document_text_iface_init (EvDocumentTextInterface *iface)
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;
2236
/* Page Transitions */
2238
pdf_document_get_page_duration (EvDocumentTransition *trans,
2241
PdfDocument *pdf_document;
2242
PopplerPage *poppler_page;
2243
gdouble duration = -1;
2245
pdf_document = PDF_DOCUMENT (trans);
2246
poppler_page = poppler_document_get_page (pdf_document->document, page);
2250
duration = poppler_page_get_duration (poppler_page);
2251
g_object_unref (poppler_page);
2256
static EvTransitionEffect *
2257
pdf_document_get_effect (EvDocumentTransition *trans,
2260
PdfDocument *pdf_document;
2261
PopplerPage *poppler_page;
2262
PopplerPageTransition *page_transition;
2263
EvTransitionEffect *effect;
2265
pdf_document = PDF_DOCUMENT (trans);
2266
poppler_page = poppler_document_get_page (pdf_document->document, page);
2271
page_transition = poppler_page_get_transition (poppler_page);
2273
if (!page_transition) {
2274
g_object_unref (poppler_page);
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,
2288
poppler_page_transition_free (page_transition);
2289
g_object_unref (poppler_page);
2295
pdf_document_page_transition_iface_init (EvDocumentTransitionInterface *iface)
2297
iface->get_page_duration = pdf_document_get_page_duration;
2298
iface->get_effect = pdf_document_get_effect;
2304
pdf_document_get_crop_box (EvDocument *document,
2308
PdfDocument *pdf_document;
2309
PopplerPage *poppler_page;
2310
PopplerRectangle poppler_rect;
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;
2322
static EvFormField *
2323
ev_form_field_from_poppler_field (PdfDocument *pdf_document,
2324
PopplerFormField *poppler_field)
2326
EvFormField *ev_field = NULL;
2329
gboolean is_read_only;
2330
PopplerAction *action;
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);
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;
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;
2346
case POPPLER_FORM_TEXT_MULTILINE:
2347
ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
2349
case POPPLER_FORM_TEXT_FILE_SELECT:
2350
ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
2354
ev_field = ev_form_field_text_new (id, ev_text_type);
2355
field_text = EV_FORM_FIELD_TEXT (ev_field);
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);
2366
case POPPLER_FORM_FIELD_BUTTON: {
2367
EvFormFieldButton *field_button;
2368
EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
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;
2374
case POPPLER_FORM_BUTTON_CHECK:
2375
ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
2377
case POPPLER_FORM_BUTTON_RADIO:
2378
ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
2382
ev_field = ev_form_field_button_new (id, ev_button_type);
2383
field_button = EV_FORM_FIELD_BUTTON (ev_field);
2385
field_button->state = poppler_form_field_button_get_state (poppler_field);
2388
case POPPLER_FORM_FIELD_CHOICE: {
2389
EvFormFieldChoice *field_choice;
2390
EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
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;
2396
case EV_FORM_FIELD_CHOICE_LIST:
2397
ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
2401
ev_field = ev_form_field_choice_new (id, ev_choice_type);
2402
field_choice = EV_FORM_FIELD_CHOICE (ev_field);
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);
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);
2415
case POPPLER_FORM_FIELD_SIGNATURE:
2417
ev_field = ev_form_field_signature_new (id);
2419
case POPPLER_FORM_FIELD_UNKNOWN:
2423
ev_field->font_size = font_size;
2424
ev_field->is_read_only = is_read_only;
2427
ev_field->activation_link = ev_link_from_action (pdf_document, action);
2432
static EvMappingList *
2433
pdf_document_forms_get_form_fields (EvDocumentForms *document,
2436
PopplerPage *poppler_page;
2437
GList *retval = NULL;
2442
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
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);
2448
for (list = fields; list; list = list->next) {
2449
PopplerFormFieldMapping *mapping;
2450
EvMapping *field_mapping;
2451
EvFormField *ev_field;
2453
mapping = (PopplerFormFieldMapping *)list->data;
2455
ev_field = ev_form_field_from_poppler_field (PDF_DOCUMENT (document), mapping->field);
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));
2467
g_object_set_data_full (G_OBJECT (ev_field),
2469
g_object_ref (mapping->field),
2470
(GDestroyNotify) g_object_unref);
2472
retval = g_list_prepend (retval, field_mapping);
2475
poppler_page_free_form_field_mapping (fields);
2477
return retval ? ev_mapping_list_new (page->index,
2478
g_list_reverse (retval),
2479
(GDestroyNotify)g_object_unref) : NULL;
2483
pdf_document_forms_document_is_modified (EvDocumentForms *document)
2485
return PDF_DOCUMENT (document)->forms_modified;
2489
pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
2493
PopplerFormField *poppler_field;
2496
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2500
text = poppler_form_field_text_get_text (poppler_field);
2506
pdf_document_forms_form_field_text_set_text (EvDocumentForms *document,
2510
PopplerFormField *poppler_field;
2512
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2516
poppler_form_field_text_set_text (poppler_field, text);
2517
PDF_DOCUMENT (document)->forms_modified = TRUE;
2521
pdf_document_forms_form_field_button_set_state (EvDocumentForms *document,
2525
PopplerFormField *poppler_field;
2527
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2531
poppler_form_field_button_set_state (poppler_field, state);
2532
PDF_DOCUMENT (document)->forms_modified = TRUE;
2536
pdf_document_forms_form_field_button_get_state (EvDocumentForms *document,
2539
PopplerFormField *poppler_field;
2542
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2546
state = poppler_form_field_button_get_state (poppler_field);
2552
pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document,
2556
PopplerFormField *poppler_field;
2559
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2563
text = poppler_form_field_choice_get_item (poppler_field, index);
2569
pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document,
2572
PopplerFormField *poppler_field;
2575
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2579
n_items = poppler_form_field_choice_get_n_items (poppler_field);
2585
pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document,
2589
PopplerFormField *poppler_field;
2592
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2596
selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
2602
pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document,
2606
PopplerFormField *poppler_field;
2608
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2612
poppler_form_field_choice_select_item (poppler_field, index);
2613
PDF_DOCUMENT (document)->forms_modified = TRUE;
2617
pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document,
2621
PopplerFormField *poppler_field;
2623
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2627
poppler_form_field_choice_toggle_item (poppler_field, index);
2628
PDF_DOCUMENT (document)->forms_modified = TRUE;
2632
pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document,
2635
PopplerFormField *poppler_field;
2637
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2641
poppler_form_field_choice_unselect_all (poppler_field);
2642
PDF_DOCUMENT (document)->forms_modified = TRUE;
2646
pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
2650
PopplerFormField *poppler_field;
2652
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2656
poppler_form_field_choice_set_text (poppler_field, text);
2657
PDF_DOCUMENT (document)->forms_modified = TRUE;
2661
pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
2664
PopplerFormField *poppler_field;
2667
poppler_field = POPPLER_FORM_FIELD (g_object_get_data (G_OBJECT (field), "poppler-field"));
2671
text = poppler_form_field_choice_get_text (poppler_field);
2677
pdf_document_document_forms_iface_init (EvDocumentFormsInterface *iface)
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;
2697
poppler_annot_color_to_gdk_color (PopplerAnnot *poppler_annot,
2700
PopplerColor *poppler_color;
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;
2708
g_free (poppler_color);
2709
} /* TODO: else use a default color */
2712
static EvAnnotationTextIcon
2713
get_annot_text_icon (PopplerAnnotText *poppler_annot)
2715
gchar *icon = poppler_annot_text_get_icon (poppler_annot);
2716
EvAnnotationTextIcon retval;
2719
return EV_ANNOTATION_TEXT_ICON_UNKNOWN;
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;
2740
retval = EV_ANNOTATION_TEXT_ICON_UNKNOWN;
2747
static const gchar *
2748
get_poppler_annot_text_icon (EvAnnotationTextIcon 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:
2771
return POPPLER_ANNOT_TEXT_ICON_NOTE;
2775
static EvAnnotation *
2776
ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot,
2779
EvAnnotation *ev_annot = NULL;
2780
const gchar *unimplemented_annot = NULL;
2781
gboolean reported_annot = FALSE;
2783
switch (poppler_annot_get_annot_type (poppler_annot)) {
2784
case POPPLER_ANNOT_TEXT: {
2785
PopplerAnnotText *poppler_text;
2786
EvAnnotationText *ev_annot_text;
2788
poppler_text = POPPLER_ANNOT_TEXT (poppler_annot);
2790
ev_annot = ev_annotation_text_new (page);
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));
2798
case POPPLER_ANNOT_FILE_ATTACHMENT: {
2799
PopplerAnnotFileAttachment *poppler_annot_attachment;
2800
PopplerAttachment *poppler_attachment;
2803
GError *error = NULL;
2805
poppler_annot_attachment = POPPLER_ANNOT_FILE_ATTACHMENT (poppler_annot);
2806
poppler_attachment = poppler_annot_file_attachment_get_attachment (poppler_annot_attachment);
2808
if (poppler_attachment &&
2809
attachment_save_to_buffer (poppler_attachment, &data, &size, &error)) {
2810
EvAttachment *ev_attachment;
2812
ev_attachment = ev_attachment_new (poppler_attachment->name,
2813
poppler_attachment->description,
2814
poppler_attachment->mtime,
2815
poppler_attachment->ctime,
2817
ev_annot = ev_annotation_attachment_new (page, ev_attachment);
2818
g_object_unref (ev_attachment);
2820
g_warning ("%s", error->message);
2821
g_error_free (error);
2824
if (poppler_attachment)
2825
g_object_unref (poppler_attachment);
2828
case POPPLER_ANNOT_LINK:
2829
case POPPLER_ANNOT_WIDGET:
2830
/* Ignore link and widgets annots since they are already handled */
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.
2849
GEnumValue *enum_value;
2850
reported_annot = TRUE;
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";
2858
GEnumValue *enum_value;
2859
reported_annot = FALSE;
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";
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);
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);
2887
contents = poppler_annot_get_contents (poppler_annot);
2889
ev_annotation_set_contents (ev_annot, contents);
2893
name = poppler_annot_get_name (poppler_annot);
2895
ev_annotation_set_name (ev_annot, name);
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);
2903
ev_annotation_set_modified (ev_annot, modified);
2907
poppler_annot_color_to_gdk_color (poppler_annot, &color);
2908
ev_annotation_set_color (ev_annot, &color);
2910
if (POPPLER_IS_ANNOT_MARKUP (poppler_annot)) {
2911
PopplerAnnotMarkup *markup;
2914
PopplerRectangle poppler_rect;
2916
markup = POPPLER_ANNOT_MARKUP (poppler_annot);
2918
if (poppler_annot_markup_get_popup_rectangle (markup, &poppler_rect)) {
2919
EvRectangle ev_rect;
2923
poppler_page_get_size (POPPLER_PAGE (page->backend_page),
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;
2930
is_open = poppler_annot_markup_get_popup_is_open (markup);
2932
g_object_set (ev_annot,
2933
"rectangle", &ev_rect,
2934
"popup_is_open", is_open,
2938
g_object_set (ev_annot,
2943
label = poppler_annot_markup_get_label (markup);
2944
opacity = poppler_annot_markup_get_opacity (markup);
2946
g_object_set (ev_annot,
2958
static EvMappingList *
2959
pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annotations,
2962
GList *retval = NULL;
2963
PdfDocument *pdf_document;
2964
PopplerPage *poppler_page;
2965
EvMappingList *mapping_list;
2971
pdf_document = PDF_DOCUMENT (document_annotations);
2972
poppler_page = POPPLER_PAGE (page->backend_page);
2974
if (pdf_document->annots) {
2975
mapping_list = (EvMappingList *)g_hash_table_lookup (pdf_document->annots,
2976
GINT_TO_POINTER (page->index));
2978
return ev_mapping_list_ref (mapping_list);
2981
annots = poppler_page_get_annot_mapping (poppler_page);
2982
poppler_page_get_size (poppler_page, NULL, &height);
2984
for (list = annots; list; list = list->next) {
2985
PopplerAnnotMapping *mapping;
2986
EvMapping *annot_mapping;
2987
EvAnnotation *ev_annot;
2989
mapping = (PopplerAnnotMapping *)list->data;
2991
ev_annot = ev_annot_from_poppler_annot (mapping->annot, page);
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);
3001
ev_annotation_set_name (ev_annot, name);
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;
3012
g_object_set_data_full (G_OBJECT (ev_annot),
3014
g_object_ref (mapping->annot),
3015
(GDestroyNotify) g_object_unref);
3017
retval = g_list_prepend (retval, annot_mapping);
3020
poppler_page_free_annot_mapping (annots);
3025
if (!pdf_document->annots) {
3026
pdf_document->annots = g_hash_table_new_full (g_direct_hash,
3028
(GDestroyNotify)NULL,
3029
(GDestroyNotify)ev_mapping_list_unref);
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));
3037
return mapping_list;
3041
pdf_document_annotations_document_is_modified (EvDocumentAnnotations *document_annotations)
3043
return PDF_DOCUMENT (document_annotations)->annots_modified;
3047
pdf_document_annotations_add_annotation (EvDocumentAnnotations *document_annotations,
3048
EvAnnotation *annot,
3051
PopplerAnnot *poppler_annot;
3052
PdfDocument *pdf_document;
3054
PopplerPage *poppler_page;
3056
EvMappingList *mapping_list;
3057
EvMapping *annot_mapping;
3058
PopplerRectangle poppler_rect;
3060
PopplerColor poppler_color;
3064
pdf_document = PDF_DOCUMENT (document_annotations);
3065
page = ev_annotation_get_page (annot);
3066
poppler_page = POPPLER_PAGE (page->backend_page);
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);
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);
3081
if (EV_IS_ANNOTATION_MARKUP (annot)) {
3082
EvAnnotationMarkup *markup = EV_ANNOTATION_MARKUP (annot);
3085
if (ev_annotation_markup_has_popup (markup)) {
3086
EvRectangle popup_rect;
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));
3098
label = ev_annotation_markup_get_label (markup);
3100
poppler_annot_markup_set_label (POPPLER_ANNOT_MARKUP (poppler_annot), label);
3103
if (EV_IS_ANNOTATION_TEXT (annot)) {
3104
EvAnnotationText *text = EV_ANNOTATION_TEXT (annot);
3105
EvAnnotationTextIcon icon;
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));
3111
poppler_page_add_annot (poppler_page, poppler_annot);
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),
3118
g_object_ref (poppler_annot),
3119
(GDestroyNotify) g_object_unref);
3121
if (pdf_document->annots) {
3122
mapping_list = (EvMappingList *)g_hash_table_lookup (pdf_document->annots,
3123
GINT_TO_POINTER (page->index));
3125
pdf_document->annots = g_hash_table_new_full (g_direct_hash,
3127
(GDestroyNotify)NULL,
3128
(GDestroyNotify)ev_mapping_list_unref);
3129
mapping_list = NULL;
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);
3137
list = g_list_append (list, annot_mapping);
3139
name = g_strdup_printf ("annot-%d-0", page->index);
3140
ev_annotation_set_name (annot, 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));
3149
pdf_document->annots_modified = TRUE;
3153
pdf_document_annotations_save_annotation (EvDocumentAnnotations *document_annotations,
3154
EvAnnotation *annot,
3155
EvAnnotationsSaveMask mask)
3157
PopplerAnnot *poppler_annot;
3159
poppler_annot = POPPLER_ANNOT (g_object_get_data (G_OBJECT (annot), "poppler-annot"));
3163
if (mask & EV_ANNOTATIONS_SAVE_CONTENTS)
3164
poppler_annot_set_contents (poppler_annot,
3165
ev_annotation_get_contents (annot));
3167
if (mask & EV_ANNOTATIONS_SAVE_COLOR) {
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);
3178
if (EV_IS_ANNOTATION_MARKUP (annot)) {
3179
EvAnnotationMarkup *ev_markup = EV_ANNOTATION_MARKUP (annot);
3180
PopplerAnnotMarkup *markup = POPPLER_ANNOT_MARKUP (poppler_annot);
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));
3190
if (EV_IS_ANNOTATION_TEXT (annot)) {
3191
EvAnnotationText *ev_text = EV_ANNOTATION_TEXT (annot);
3192
PopplerAnnotText *text = POPPLER_ANNOT_TEXT (poppler_annot);
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));
3198
if (mask & EV_ANNOTATIONS_SAVE_TEXT_ICON) {
3199
EvAnnotationTextIcon icon;
3201
icon = ev_annotation_text_get_icon (ev_text);
3202
poppler_annot_text_set_icon (text, get_poppler_annot_text_icon (icon));
3206
PDF_DOCUMENT (document_annotations)->annots_modified = TRUE;
3210
pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface)
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;
3219
struct SaveToBufferData {
3225
attachment_save_to_buffer_callback (const gchar *buf,
3230
struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
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);
3238
sdata->buffer = new_buffer;
3239
sdata->max = new_max;
3242
memcpy (sdata->buffer + sdata->len, buf, count);
3243
sdata->len += count;
3249
attachment_save_to_buffer (PopplerAttachment *attachment,
3254
static const gint initial_max = 1024;
3255
struct SaveToBufferData sdata;
3260
sdata.buffer = (gchar *) g_malloc (initial_max);
3261
sdata.max = initial_max;
3264
if (! poppler_attachment_save_to_callback (attachment,
3265
attachment_save_to_buffer_callback,
3268
g_free (sdata.buffer);
3272
*buffer = sdata.buffer;
3273
*buffer_size = sdata.len;
3279
pdf_document_attachments_get_attachments (EvDocumentAttachments *document)
3281
PdfDocument *pdf_document = PDF_DOCUMENT (document);
3284
GList *retval = NULL;
3286
attachments = poppler_document_get_attachments (pdf_document->document);
3288
for (list = attachments; list; list = list->next) {
3289
PopplerAttachment *attachment;
3290
EvAttachment *ev_attachment;
3293
GError *error = NULL;
3295
attachment = (PopplerAttachment *) list->data;
3297
if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
3298
ev_attachment = ev_attachment_new (attachment->name,
3299
attachment->description,
3304
retval = g_list_prepend (retval, ev_attachment);
3307
g_warning ("%s", error->message);
3308
g_error_free (error);
3314
g_object_unref (attachment);
3317
return g_list_reverse (retval);
3321
pdf_document_attachments_has_attachments (EvDocumentAttachments *document)
3323
PdfDocument *pdf_document = PDF_DOCUMENT (document);
3325
return poppler_document_has_attachments (pdf_document->document);
3329
pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface)
3331
iface->has_attachments = pdf_document_attachments_has_attachments;
3332
iface->get_attachments = pdf_document_attachments_get_attachments;
3337
pdf_document_layers_has_layers (EvDocumentLayers *document)
3339
PdfDocument *pdf_document = PDF_DOCUMENT (document);
3340
PopplerLayersIter *iter;
3342
iter = poppler_layers_iter_new (pdf_document->document);
3345
poppler_layers_iter_free (iter);
3351
build_layers_tree (PdfDocument *pdf_document,
3352
GtkTreeModel *model,
3353
GtkTreeIter *parent,
3354
PopplerLayersIter *iter)
3357
GtkTreeIter tree_iter;
3358
PopplerLayersIter *child;
3359
PopplerLayer *layer;
3360
EvLayer *ev_layer = NULL;
3365
layer = poppler_layers_iter_get_layer (iter);
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),
3372
g_object_set_data_full (G_OBJECT (ev_layer),
3374
g_object_ref (layer),
3375
(GDestroyNotify) g_object_unref);
3379
title = poppler_layers_iter_get_title (iter);
3380
markup = g_markup_escape_text (title, -1);
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,
3397
g_object_unref (ev_layer);
3400
child = poppler_layers_iter_get_child (iter);
3402
build_layers_tree (pdf_document, model, &tree_iter, child);
3403
poppler_layers_iter_free (child);
3404
} while (poppler_layers_iter_next (iter));
3407
static GtkTreeModel *
3408
pdf_document_layers_get_layers (EvDocumentLayers *document)
3410
GtkTreeModel *model = NULL;
3411
PdfDocument *pdf_document = PDF_DOCUMENT (document);
3412
PopplerLayersIter *iter;
3414
iter = poppler_layers_iter_new (pdf_document->document);
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);
3430
pdf_document_layers_show_layer (EvDocumentLayers *document,
3433
PopplerLayer *poppler_layer;
3435
poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer"));
3436
poppler_layer_show (poppler_layer);
3440
pdf_document_layers_hide_layer (EvDocumentLayers *document,
3443
PopplerLayer *poppler_layer;
3445
poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer"));
3446
poppler_layer_hide (poppler_layer);
3450
pdf_document_layers_layer_is_visible (EvDocumentLayers *document,
3453
PopplerLayer *poppler_layer;
3455
poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer"));
3456
return poppler_layer_is_visible (poppler_layer);
3460
pdf_document_document_layers_iface_init (EvDocumentLayersInterface *iface)
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;