X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=backend%2Fpdf%2Fev-poppler.cc;h=753fedc36f12385425c24b9171b5bc840af2caa8;hb=1d6c41200f621a43e92deda5b5d682413572d2a2;hp=389b436e9388a9db3f246b7b059a7aca893aa1be;hpb=ee37f085119db53f4108c3d5c398b2104bb3cdf2;p=evince.git diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index 389b436e..753fedc3 100644 --- a/backend/pdf/ev-poppler.cc +++ b/backend/pdf/ev-poppler.cc @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" @@ -37,20 +37,19 @@ #include "ev-poppler.h" #include "ev-file-exporter.h" -#include "ev-mapping.h" #include "ev-document-find.h" #include "ev-document-misc.h" #include "ev-document-links.h" #include "ev-document-images.h" #include "ev-document-fonts.h" #include "ev-document-security.h" -#include "ev-document-thumbnails.h" #include "ev-document-transition.h" #include "ev-document-forms.h" #include "ev-document-layers.h" #include "ev-document-print.h" #include "ev-document-annotations.h" #include "ev-document-attachments.h" +#include "ev-document-text.h" #include "ev-selection.h" #include "ev-transition-effect.h" #include "ev-attachment.h" @@ -61,7 +60,7 @@ #include #include -#if (defined (HAVE_POPPLER_PAGE_RENDER)) && (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS)) +#if (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS)) #define HAVE_CAIRO_PRINT #endif @@ -72,15 +71,6 @@ /* license field from Creative Commons schema, http://creativecommons.org/ns */ #define LICENSE_URI "/x:xmpmeta/rdf:RDF/rdf:Description/cc:license/@rdf:resource" -typedef struct { - PdfDocument *document; - char *text; - GList **pages; - guint idle; - int start_page; - int search_page; -} PdfDocumentSearch; - typedef struct { EvFileExporterFormat format; @@ -110,45 +100,38 @@ struct _PdfDocument PopplerDocument *document; gchar *password; - gboolean modified; + gboolean forms_modified; + gboolean annots_modified; PopplerFontInfo *font_info; PopplerFontsIter *fonts_iter; int fonts_scanned_pages; - PdfDocumentSearch *search; PdfPrintContext *print_ctx; - GList *layers; + GHashTable *annots; }; -static void pdf_document_security_iface_init (EvDocumentSecurityIface *iface); -static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface); -static void pdf_document_document_links_iface_init (EvDocumentLinksIface *iface); -static void pdf_document_document_images_iface_init (EvDocumentImagesIface *iface); -static void pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface); -static void pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface); -static void pdf_document_document_layers_iface_init (EvDocumentLayersIface *iface); -#ifdef HAVE_POPPLER_PAGE_RENDER -static void pdf_document_document_print_iface_init (EvDocumentPrintIface *iface); -#endif -static void pdf_document_document_annotations_iface_init (EvDocumentAnnotationsIface *iface); -static void pdf_document_document_attachments_iface_init (EvDocumentAttachmentsIface *iface); -static void pdf_document_find_iface_init (EvDocumentFindIface *iface); -static void pdf_document_file_exporter_iface_init (EvFileExporterIface *iface); -static void pdf_selection_iface_init (EvSelectionIface *iface); -static void pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface); -static void pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails, - EvRenderContext *rc, - gint *width, - gint *height); -static int pdf_document_get_n_pages (EvDocument *document); +static void pdf_document_security_iface_init (EvDocumentSecurityInterface *iface); +static void pdf_document_document_links_iface_init (EvDocumentLinksInterface *iface); +static void pdf_document_document_images_iface_init (EvDocumentImagesInterface *iface); +static void pdf_document_document_forms_iface_init (EvDocumentFormsInterface *iface); +static void pdf_document_document_fonts_iface_init (EvDocumentFontsInterface *iface); +static void pdf_document_document_layers_iface_init (EvDocumentLayersInterface *iface); +static void pdf_document_document_print_iface_init (EvDocumentPrintInterface *iface); +static void pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface); +static void pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface); +static void pdf_document_find_iface_init (EvDocumentFindInterface *iface); +static void pdf_document_file_exporter_iface_init (EvFileExporterInterface *iface); +static void pdf_selection_iface_init (EvSelectionInterface *iface); +static void pdf_document_page_transition_iface_init (EvDocumentTransitionInterface *iface); +static void pdf_document_text_iface_init (EvDocumentTextInterface *iface); +static int pdf_document_get_n_pages (EvDocument *document); static EvLinkDest *ev_link_dest_from_dest (PdfDocument *pdf_document, PopplerDest *dest); static EvLink *ev_link_from_action (PdfDocument *pdf_document, PopplerAction *action); -static void pdf_document_search_free (PdfDocumentSearch *search); static void pdf_print_context_free (PdfPrintContext *ctx); static gboolean attachment_save_to_buffer (PopplerAttachment *attachment, gchar **buffer, @@ -159,8 +142,6 @@ EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document, { EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY, pdf_document_security_iface_init); - EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, - pdf_document_document_thumbnails_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS, pdf_document_document_links_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES, @@ -171,10 +152,8 @@ EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document, pdf_document_document_fonts_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LAYERS, pdf_document_document_layers_iface_init); -#ifdef HAVE_POPPLER_PAGE_RENDER EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT, pdf_document_document_print_iface_init); -#endif EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_ANNOTATIONS, pdf_document_document_annotations_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_ATTACHMENTS, @@ -187,29 +166,10 @@ EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document, pdf_selection_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION, pdf_document_page_transition_iface_init); + EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TEXT, + pdf_document_text_iface_init); }); -static void -pdf_document_search_free (PdfDocumentSearch *search) -{ - PdfDocument *pdf_document = search->document; - int n_pages; - int i; - - if (search->idle != 0) - g_source_remove (search->idle); - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document)); - for (i = 0; i < n_pages; i++) { - g_list_foreach (search->pages[i], (GFunc) g_free, NULL); - g_list_free (search->pages[i]); - } - g_free (search->pages); - - g_free (search->text); - g_free (search); -} - static void pdf_document_dispose (GObject *object) { @@ -219,10 +179,10 @@ pdf_document_dispose (GObject *object) pdf_print_context_free (pdf_document->print_ctx); pdf_document->print_ctx = NULL; } - - if (pdf_document->search) { - pdf_document_search_free (pdf_document->search); - pdf_document->search = NULL; + + if (pdf_document->annots) { + g_hash_table_destroy (pdf_document->annots); + pdf_document->annots = NULL; } if (pdf_document->document) { @@ -237,11 +197,6 @@ pdf_document_dispose (GObject *object) poppler_fonts_iter_free (pdf_document->fonts_iter); } - if (pdf_document->layers) { - g_list_foreach (pdf_document->layers, (GFunc)g_object_unref, NULL); - g_list_free (pdf_document->layers); - } - G_OBJECT_CLASS (pdf_document_parent_class)->dispose (object); } @@ -288,9 +243,13 @@ pdf_document_save (EvDocument *document, gboolean retval; GError *poppler_error = NULL; - if (pdf_document->modified) { + if (pdf_document->forms_modified || pdf_document->annots_modified) { retval = poppler_document_save (pdf_document->document, uri, &poppler_error); + if (retval) { + pdf_document->forms_modified = FALSE; + pdf_document->annots_modified = FALSE; + } } else { retval = poppler_document_save_a_copy (pdf_document->document, uri, &poppler_error); @@ -376,8 +335,6 @@ pdf_page_render (PopplerPage *page, EvRenderContext *rc) { cairo_surface_t *surface; - -#ifdef HAVE_POPPLER_PAGE_RENDER cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, @@ -406,24 +363,8 @@ pdf_page_render (PopplerPage *page, cairo_paint (cr); cairo_destroy (cr); -#else /* HAVE_POPPLER_PAGE_RENDER */ - GdkPixbuf *pixbuf; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE, 8, - width, height); - - poppler_page_render_to_pixbuf (page, - 0, 0, - width, height, - rc->scale, - rc->rotation, - pixbuf); - surface = ev_document_misc_surface_from_pixbuf (pixbuf); - g_object_unref (pixbuf); -#endif /* HAVE_POPPLER_PAGE_RENDER */ - return surface; + return surface; } static cairo_surface_t * @@ -452,6 +393,84 @@ pdf_document_render (EvDocument *document, width, height, rc); } +static GdkPixbuf * +make_thumbnail_for_page (PopplerPage *poppler_page, + EvRenderContext *rc, + gint width, + gint height) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + + ev_document_fc_mutex_lock (); + surface = pdf_page_render (poppler_page, width, height, rc); + ev_document_fc_mutex_unlock (); + + pixbuf = ev_document_misc_pixbuf_from_surface (surface); + cairo_surface_destroy (surface); + + return pixbuf; +} + +static GdkPixbuf * +pdf_document_get_thumbnail (EvDocument *document, + EvRenderContext *rc) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerPage *poppler_page; + cairo_surface_t *surface; + GdkPixbuf *pixbuf = NULL; + GdkPixbuf *border_pixbuf; + double page_width, page_height; + gint width, height; + + poppler_page = POPPLER_PAGE (rc->page->backend_page); + + poppler_page_get_size (poppler_page, + &page_width, &page_height); + + width = MAX ((gint)(page_width * rc->scale + 0.5), 1); + height = MAX ((gint)(page_height * rc->scale + 0.5), 1); + + if (rc->rotation == 90 || rc->rotation == 270) { + gint temp; + + temp = width; + width = height; + height = temp; + } + + surface = poppler_page_get_thumbnail (poppler_page); + if (surface) { + pixbuf = ev_document_misc_pixbuf_from_surface (surface); + cairo_surface_destroy (surface); + } + + if (pixbuf != NULL) { + int thumb_width = (rc->rotation == 90 || rc->rotation == 270) ? + gdk_pixbuf_get_height (pixbuf) : + gdk_pixbuf_get_width (pixbuf); + + if (thumb_width == width) { + GdkPixbuf *rotated_pixbuf; + + rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, + (GdkPixbufRotation) (360 - rc->rotation)); + g_object_unref (pixbuf); + pixbuf = rotated_pixbuf; + } else { + /* The provided thumbnail has a different size */ + g_object_unref (pixbuf); + pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height); + } + } else { + /* There is no provided thumbnail. We need to make one. */ + pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height); + } + + return pixbuf; +} + /* reference: 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 */ static char * @@ -685,6 +704,7 @@ pdf_document_get_info (EvDocument *document) PopplerPermissions permissions; EvPage *page; char *metadata; + gboolean linearized; info = g_new0 (EvDocumentInfo, 1); @@ -721,7 +741,7 @@ pdf_document_get_info (EvDocument *document) "producer", &(info->producer), "creation-date", &(info->creation_date), "mod-date", &(info->modified_date), - "linearized", &(info->linearized), + "linearized", &linearized, "metadata", &metadata, NULL); @@ -827,6 +847,8 @@ pdf_document_get_info (EvDocument *document) info->security = g_strdup (_("No")); } + info->linearized = linearized ? g_strdup (_("Yes")) : g_strdup (_("No")); + return info; } @@ -853,6 +875,12 @@ pdf_document_get_backend_info (EvDocument *document, EvDocumentBackendInfo *info return TRUE; } +static gboolean +pdf_document_support_synctex (EvDocument *document) +{ + return TRUE; +} + static void pdf_document_class_init (PdfDocumentClass *klass) { @@ -868,8 +896,10 @@ pdf_document_class_init (PdfDocumentClass *klass) ev_document_class->get_page_size = pdf_document_get_page_size; ev_document_class->get_page_label = pdf_document_get_page_label; ev_document_class->render = pdf_document_render; + ev_document_class->get_thumbnail = pdf_document_get_thumbnail; ev_document_class->get_info = pdf_document_get_info; ev_document_class->get_backend_info = pdf_document_get_backend_info; + ev_document_class->support_synctex = pdf_document_support_synctex; } /* EvDocumentSecurity */ @@ -893,7 +923,7 @@ pdf_document_set_password (EvDocumentSecurity *document_security, } static void -pdf_document_security_iface_init (EvDocumentSecurityIface *iface) +pdf_document_security_iface_init (EvDocumentSecurityInterface *iface) { iface->has_document_security = pdf_document_has_document_security; iface->set_password = pdf_document_set_password; @@ -1013,7 +1043,7 @@ pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts, } static void -pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface) +pdf_document_document_fonts_iface_init (EvDocumentFontsInterface *iface) { iface->fill_model = pdf_document_fonts_fill_model; iface->scan = pdf_document_fonts_scan; @@ -1163,6 +1193,51 @@ ev_link_from_action (PdfDocument *pdf_document, case POPPLER_ACTION_MOVIE: unimplemented_action = "POPPLER_ACTION_MOVIE"; break; + case POPPLER_ACTION_RENDITION: + unimplemented_action = "POPPLER_ACTION_RENDITION"; + break; + case POPPLER_ACTION_OCG_STATE: { + GList *on_list = NULL; + GList *off_list = NULL; + GList *toggle_list = NULL; + GList *l, *m; + + for (l = action->ocg_state.state_list; l; l = g_list_next (l)) { + PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data; + + for (m = action_layer->layers; m; m = g_list_next (m)) { + PopplerLayer *layer = (PopplerLayer *)m->data; + EvLayer *ev_layer; + + ev_layer = ev_layer_new (poppler_layer_is_parent (layer), + poppler_layer_get_radio_button_group_id (layer)); + g_object_set_data_full (G_OBJECT (ev_layer), + "poppler-layer", + g_object_ref (layer), + (GDestroyNotify)g_object_unref); + + switch (action_layer->action) { + case POPPLER_ACTION_LAYER_ON: + on_list = g_list_prepend (on_list, ev_layer); + break; + case POPPLER_ACTION_LAYER_OFF: + off_list = g_list_prepend (off_list, ev_layer); + break; + case POPPLER_ACTION_LAYER_TOGGLE: + toggle_list = g_list_prepend (toggle_list, ev_layer); + break; + } + } + } + + /* The action takes the ownership of the lists */ + ev_action = ev_link_action_new_layers_state (g_list_reverse (on_list), + g_list_reverse (off_list), + g_list_reverse (toggle_list)); + + + } + break; case POPPLER_ACTION_UNKNOWN: unimplemented_action = "POPPLER_ACTION_UNKNOWN"; } @@ -1199,36 +1274,7 @@ build_tree (PdfDocument *pdf_document, if (!action) continue; - switch (action->type) { - case POPPLER_ACTION_GOTO_DEST: { - /* For bookmarks, solve named destinations */ - if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) { - PopplerDest *dest; - EvLinkDest *ev_dest = NULL; - EvLinkAction *ev_action; - - dest = poppler_document_find_dest (pdf_document->document, - action->goto_dest.dest->named_dest); - if (!dest) { - link = ev_link_from_action (pdf_document, action); - break; - } - - ev_dest = ev_link_dest_from_dest (pdf_document, dest); - poppler_dest_free (dest); - - ev_action = ev_link_action_new_dest (ev_dest); - link = ev_link_new (action->any.title, ev_action); - } else { - link = ev_link_from_action (pdf_document, action); - } - } - break; - default: - link = ev_link_from_action (pdf_document, action); - break; - } - + link = ev_link_from_action (pdf_document, action); if (!link || strlen (ev_link_get_title (link)) <= 0) { poppler_action_free (action); if (link) @@ -1282,7 +1328,7 @@ pdf_document_links_get_links_model (EvDocumentLinks *document_links) return model; } -static GList * +static EvMappingList * pdf_document_links_get_links (EvDocumentLinks *document_links, EvPage *page) { @@ -1317,7 +1363,7 @@ pdf_document_links_get_links (EvDocumentLinks *document_links, poppler_page_free_link_mapping (mapping_list); - return g_list_reverse (retval); + return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref); } static EvLinkDest * @@ -1339,16 +1385,36 @@ pdf_document_links_find_link_dest (EvDocumentLinks *document_links, return ev_dest; } +static gint +pdf_document_links_find_link_page (EvDocumentLinks *document_links, + const gchar *link_name) +{ + PdfDocument *pdf_document; + PopplerDest *dest; + gint retval = -1; + + pdf_document = PDF_DOCUMENT (document_links); + dest = poppler_document_find_dest (pdf_document->document, + link_name); + if (dest) { + retval = dest->page_num - 1; + poppler_dest_free (dest); + } + + return retval; +} + static void -pdf_document_document_links_iface_init (EvDocumentLinksIface *iface) +pdf_document_document_links_iface_init (EvDocumentLinksInterface *iface) { iface->has_document_links = pdf_document_links_has_document_links; iface->get_links_model = pdf_document_links_get_links_model; iface->get_links = pdf_document_links_get_links; iface->find_link_dest = pdf_document_links_find_link_dest; + iface->find_link_page = pdf_document_links_find_link_page; } -static GList * +static EvMappingList * pdf_document_images_get_image_mapping (EvDocumentImages *document_images, EvPage *page) { @@ -1381,7 +1447,7 @@ pdf_document_images_get_image_mapping (EvDocumentImages *document_images, poppler_page_free_image_mapping (mapping_list); - return g_list_reverse (retval); + return ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref); } GdkPixbuf * @@ -1389,7 +1455,6 @@ pdf_document_images_get_image (EvDocumentImages *document_images, EvImage *image) { GdkPixbuf *retval = NULL; -#ifdef HAVE_POPPLER_PAGE_GET_IMAGE PdfDocument *pdf_document; PopplerPage *poppler_page; cairo_surface_t *surface; @@ -1405,139 +1470,17 @@ pdf_document_images_get_image (EvDocumentImages *document_images, } g_object_unref (poppler_page); -#endif + return retval; } static void -pdf_document_document_images_iface_init (EvDocumentImagesIface *iface) +pdf_document_document_images_iface_init (EvDocumentImagesInterface *iface) { iface->get_image_mapping = pdf_document_images_get_image_mapping; iface->get_image = pdf_document_images_get_image; } -static GdkPixbuf * -make_thumbnail_for_page (PopplerPage *poppler_page, - EvRenderContext *rc, - gint width, - gint height) -{ - GdkPixbuf *pixbuf; - -#ifdef POPPLER_WITH_GDK - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, - width, height); - gdk_pixbuf_fill (pixbuf, 0xffffffff); - - ev_document_fc_mutex_lock (); - poppler_page_render_to_pixbuf (poppler_page, 0, 0, - width, height, - rc->scale, rc->rotation, pixbuf); - ev_document_fc_mutex_unlock (); -#else - cairo_surface_t *surface; - - ev_document_fc_mutex_lock (); - surface = pdf_page_render (poppler_page, width, height, rc); - ev_document_fc_mutex_unlock (); - - pixbuf = ev_document_misc_pixbuf_from_surface (surface); - cairo_surface_destroy (surface); -#endif /* POPPLER_WITH_GDK */ - - return pixbuf; -} - -static GdkPixbuf * -pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails, - EvRenderContext *rc, - gboolean border) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (document_thumbnails); - PopplerPage *poppler_page; - GdkPixbuf *pixbuf = NULL; - GdkPixbuf *border_pixbuf; - gint width, height; - - poppler_page = POPPLER_PAGE (rc->page->backend_page); - - pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document), - rc, &width, &height); - -#ifdef POPPLER_WITH_GDK - pixbuf = poppler_page_get_thumbnail_pixbuf (poppler_page); -#else - cairo_surface_t *surface; - - surface = poppler_page_get_thumbnail (poppler_page); - if (surface) { - pixbuf = ev_document_misc_pixbuf_from_surface (surface); - cairo_surface_destroy (surface); - } -#endif /* POPPLER_WITH_GDK */ - - if (pixbuf != NULL) { - int thumb_width = (rc->rotation == 90 || rc->rotation == 270) ? - gdk_pixbuf_get_height (pixbuf) : - gdk_pixbuf_get_width (pixbuf); - - if (thumb_width == width) { - GdkPixbuf *rotated_pixbuf; - - rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, - (GdkPixbufRotation) (360 - rc->rotation)); - g_object_unref (pixbuf); - pixbuf = rotated_pixbuf; - } else { - /* The provided thumbnail has a different size */ - g_object_unref (pixbuf); - pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height); - } - } else { - /* There is no provided thumbnail. We need to make one. */ - pixbuf = make_thumbnail_for_page (poppler_page, rc, width, height); - } - - if (border && pixbuf) { - border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf); - g_object_unref (pixbuf); - pixbuf = border_pixbuf; - } - - return pixbuf; -} - -static void -pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails, - EvRenderContext *rc, - gint *width, - gint *height) -{ - double page_width, page_height; - - poppler_page_get_size (POPPLER_PAGE (rc->page->backend_page), - &page_width, &page_height); - - *width = MAX ((gint)(page_width * rc->scale + 0.5), 1); - *height = MAX ((gint)(page_height * rc->scale + 0.5), 1); - - if (rc->rotation == 90 || rc->rotation == 270) { - gint temp; - - temp = *width; - *width = *height; - *height = temp; - } -} - -static void -pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface) -{ - iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail; - iface->get_dimensions = pdf_document_thumbnails_get_dimensions; -} - - static GList * pdf_document_find_find_text (EvDocumentFind *document_find, EvPage *page, @@ -1547,7 +1490,8 @@ pdf_document_find_find_text (EvDocumentFind *document_find, GList *matches, *l; PopplerPage *poppler_page; gdouble height; - + GList *retval = NULL; + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); g_return_val_if_fail (text != NULL, NULL); @@ -1560,18 +1504,26 @@ pdf_document_find_find_text (EvDocumentFind *document_find, poppler_page_get_size (poppler_page, NULL, &height); for (l = matches; l && l->data; l = g_list_next (l)) { PopplerRectangle *rect = (PopplerRectangle *)l->data; - gdouble tmp; + EvRectangle *ev_rect; + + ev_rect = ev_rectangle_new (); + ev_rect->x1 = rect->x1; + ev_rect->x2 = rect->x2; + /* Invert this for X-style coordinates */ + ev_rect->y1 = height - rect->y2; + ev_rect->y2 = height - rect->y1; - tmp = rect->y1; - rect->y1 = height - rect->y2; - rect->y2 = height - tmp; + retval = g_list_prepend (retval, ev_rect); } - - return matches; + + g_list_foreach (matches, (GFunc)poppler_rectangle_free, NULL); + g_list_free (matches); + + return g_list_reverse (retval); } static void -pdf_document_find_iface_init (EvDocumentFindIface *iface) +pdf_document_find_iface_init (EvDocumentFindInterface *iface) { iface->find_text = pdf_document_find_find_text; } @@ -1841,21 +1793,17 @@ pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter) EV_FILE_EXPORTER_CAN_REVERSE | EV_FILE_EXPORTER_CAN_SCALE | #ifdef HAVE_CAIRO_PRINT -#ifdef HAVE_POPPLER_PAGE_RENDER EV_FILE_EXPORTER_CAN_NUMBER_UP | #endif -#endif #ifdef HAVE_CAIRO_PDF -#ifdef HAVE_POPPLER_PAGE_RENDER EV_FILE_EXPORTER_CAN_GENERATE_PDF | -#endif #endif EV_FILE_EXPORTER_CAN_GENERATE_PS); } static void -pdf_document_file_exporter_iface_init (EvFileExporterIface *iface) +pdf_document_file_exporter_iface_init (EvFileExporterInterface *iface) { iface->begin = pdf_document_file_exporter_begin; iface->begin_page = pdf_document_file_exporter_begin_page; @@ -1865,7 +1813,6 @@ pdf_document_file_exporter_iface_init (EvFileExporterIface *iface) iface->get_capabilities = pdf_document_file_exporter_get_capabilities; } -#ifdef HAVE_POPPLER_PAGE_RENDER /* EvDocumentPrint */ static void pdf_document_print_print_page (EvDocumentPrint *document, @@ -1878,11 +1825,10 @@ pdf_document_print_print_page (EvDocumentPrint *document, } static void -pdf_document_document_print_iface_init (EvDocumentPrintIface *iface) +pdf_document_document_print_iface_init (EvDocumentPrintInterface *iface) { iface->print_page = pdf_document_print_print_page; } -#endif /* HAVE_POPPLER_PAGE_RENDER */ static void pdf_selection_render_selection (EvSelection *selection, @@ -1895,6 +1841,8 @@ pdf_selection_render_selection (EvSelection *selection, GdkColor *base) { PopplerPage *poppler_page; + cairo_t *cr; + PopplerColor text_color, base_color; double width_points, height_points; gint width, height; @@ -1905,10 +1853,6 @@ pdf_selection_render_selection (EvSelection *selection, width = (int) ((width_points * rc->scale) + 0.5); height = (int) ((height_points * rc->scale) + 0.5); -#ifdef HAVE_POPPLER_PAGE_RENDER - cairo_t *cr; - PopplerColor text_color, base_color; - text_color.red = text->red; text_color.green = text->green; text_color.blue = text->blue; @@ -1937,132 +1881,131 @@ pdf_selection_render_selection (EvSelection *selection, &text_color, &base_color); cairo_destroy (cr); -#else /* HAVE_POPPLER_PAGE_RENDER */ - GdkPixbuf *pixbuf; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, 8, - width, height); - - poppler_page_render_selection_to_pixbuf (poppler_page, - rc->scale, rc->rotation, pixbuf, - (PopplerRectangle *)points, - (PopplerRectangle *)old_points, - (PopplerSelectionStyle)style, - text, - base); - if (*surface) - cairo_surface_destroy (*surface); - *surface = ev_document_misc_surface_from_pixbuf (pixbuf); - g_object_unref (pixbuf); -#endif /* HAVE_POPPLER_PAGE_RENDER */ } static gchar * pdf_selection_get_selected_text (EvSelection *selection, - EvRenderContext *rc, + EvPage *page, EvSelectionStyle style, EvRectangle *points) { - PopplerPage *poppler_page; - PopplerRectangle r; - double height; - char *retval; - - poppler_page = POPPLER_PAGE (rc->page->backend_page); - - poppler_page_get_size (poppler_page, NULL, &height); - r.x1 = points->x1; - r.y1 = height - points->y2; - r.x2 = points->x2; - r.y2 = height - points->y1; - - retval = poppler_page_get_text (poppler_page, - (PopplerSelectionStyle)style, - &r); + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); - return retval; + return poppler_page_get_selected_text (POPPLER_PAGE (page->backend_page), + (PopplerSelectionStyle)style, + (PopplerRectangle *)points); } -static GdkRegion * -create_gdk_region_from_poppler_region (GList *region) +static cairo_region_t * +create_region_from_poppler_region (GList *region, gdouble scale) { GList *l; - GdkRegion *retval; - - retval = gdk_region_new (); - + cairo_region_t *retval; + + retval = cairo_region_create (); + for (l = region; l; l = g_list_next (l)) { - PopplerRectangle *rectangle; - GdkRectangle rect; - + PopplerRectangle *rectangle; + cairo_rectangle_int_t rect; + rectangle = (PopplerRectangle *)l->data; - - rect.x = (gint) rectangle->x1; - rect.y = (gint) rectangle->y1; - rect.width = (gint) (rectangle->x2 - rectangle->x1); - rect.height = (gint) (rectangle->y2 - rectangle->y1); - gdk_region_union_with_rect (retval, &rect); - + + rect.x = (gint) ((rectangle->x1 * scale) + 0.5); + rect.y = (gint) ((rectangle->y1 * scale) + 0.5); + rect.width = (gint) (((rectangle->x2 - rectangle->x1) * scale) + 0.5); + rect.height = (gint) (((rectangle->y2 - rectangle->y1) * scale) + 0.5); + cairo_region_union_rectangle (retval, &rect); + poppler_rectangle_free (rectangle); } return retval; } -static GdkRegion * +static cairo_region_t * pdf_selection_get_selection_region (EvSelection *selection, EvRenderContext *rc, EvSelectionStyle style, EvRectangle *points) { - PopplerPage *poppler_page; - GdkRegion *retval; - GList *region; + PopplerPage *poppler_page; + cairo_region_t *retval; + GList *region; poppler_page = POPPLER_PAGE (rc->page->backend_page); - region = poppler_page_get_selection_region (poppler_page, - rc->scale, + 1.0, (PopplerSelectionStyle)style, (PopplerRectangle *) points); - retval = create_gdk_region_from_poppler_region (region); + retval = create_region_from_poppler_region (region, rc->scale); g_list_free (region); return retval; } -static GdkRegion * -pdf_selection_get_selection_map (EvSelection *selection, - EvPage *page) +static void +pdf_selection_iface_init (EvSelectionInterface *iface) +{ + iface->render_selection = pdf_selection_render_selection; + iface->get_selected_text = pdf_selection_get_selected_text; + iface->get_selection_region = pdf_selection_get_selection_region; +} + + +/* EvDocumentText */ +static cairo_region_t * +pdf_document_text_get_text_mapping (EvDocumentText *document_text, + EvPage *page) { PopplerPage *poppler_page; PopplerRectangle points; GList *region; - GdkRegion *retval; + cairo_region_t *retval; + + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); poppler_page = POPPLER_PAGE (page->backend_page); points.x1 = 0.0; points.y1 = 0.0; poppler_page_get_size (poppler_page, &(points.x2), &(points.y2)); - + region = poppler_page_get_selection_region (poppler_page, 1.0, POPPLER_SELECTION_GLYPH, &points); - retval = create_gdk_region_from_poppler_region (region); + retval = create_region_from_poppler_region (region, 1.0); g_list_free (region); return retval; } +static gchar * +pdf_document_text_get_text (EvDocumentText *selection, + EvPage *page) +{ + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); + + return poppler_page_get_text (POPPLER_PAGE (page->backend_page)); +} + +static gboolean +pdf_document_text_get_text_layout (EvDocumentText *selection, + EvPage *page, + EvRectangle **areas, + guint *n_areas) +{ + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), FALSE); + + return poppler_page_get_text_layout (POPPLER_PAGE (page->backend_page), + (PopplerRectangle **)areas, n_areas); +} + static void -pdf_selection_iface_init (EvSelectionIface *iface) +pdf_document_text_iface_init (EvDocumentTextInterface *iface) { - iface->render_selection = pdf_selection_render_selection; - iface->get_selected_text = pdf_selection_get_selected_text; - iface->get_selection_region = pdf_selection_get_selection_region; - iface->get_selection_map = pdf_selection_get_selection_map; + iface->get_text_mapping = pdf_document_text_get_text_mapping; + iface->get_text = pdf_document_text_get_text; + iface->get_text_layout = pdf_document_text_get_text_layout; } /* Page Transitions */ @@ -2124,7 +2067,7 @@ pdf_document_get_effect (EvDocumentTransition *trans, } static void -pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface) +pdf_document_page_transition_iface_init (EvDocumentTransitionInterface *iface) { iface->get_page_duration = pdf_document_get_page_duration; iface->get_effect = pdf_document_get_effect; @@ -2253,7 +2196,7 @@ ev_form_field_from_poppler_field (PopplerFormField *poppler_field) return ev_field; } -static GList * +static EvMappingList * pdf_document_forms_get_form_fields (EvDocumentForms *document, EvPage *page) { @@ -2298,7 +2241,15 @@ pdf_document_forms_get_form_fields (EvDocumentForms *document, poppler_page_free_form_field_mapping (fields); - return g_list_reverse (retval); + return retval ? ev_mapping_list_new (page->index, + g_list_reverse (retval), + (GDestroyNotify)g_object_unref) : NULL; +} + +static gboolean +pdf_document_forms_document_is_modified (EvDocumentForms *document) +{ + return PDF_DOCUMENT (document)->forms_modified; } static gchar * @@ -2330,7 +2281,7 @@ pdf_document_forms_form_field_text_set_text (EvDocumentForms *document, return; poppler_form_field_text_set_text (poppler_field, text); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static void @@ -2345,7 +2296,7 @@ pdf_document_forms_form_field_button_set_state (EvDocumentForms *document, return; poppler_form_field_button_set_state (poppler_field, state); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static gboolean @@ -2426,7 +2377,7 @@ pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document, return; poppler_form_field_choice_select_item (poppler_field, index); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static void @@ -2441,7 +2392,7 @@ pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document, return; poppler_form_field_choice_toggle_item (poppler_field, index); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static void @@ -2455,7 +2406,7 @@ pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document, return; poppler_form_field_choice_unselect_all (poppler_field); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static void @@ -2470,7 +2421,7 @@ pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document, return; poppler_form_field_choice_set_text (poppler_field, text); - PDF_DOCUMENT (document)->modified = TRUE; + PDF_DOCUMENT (document)->forms_modified = TRUE; } static gchar * @@ -2490,9 +2441,10 @@ pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document, } static void -pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface) +pdf_document_document_forms_iface_init (EvDocumentFormsInterface *iface) { iface->get_form_fields = pdf_document_forms_get_form_fields; + iface->document_is_modified = pdf_document_forms_document_is_modified; iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text; iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text; iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state; @@ -2524,6 +2476,69 @@ poppler_annot_color_to_gdk_color (PopplerAnnot *poppler_annot, } /* TODO: else use a default color */ } +static EvAnnotationTextIcon +get_annot_text_icon (PopplerAnnotText *poppler_annot) +{ + gchar *icon = poppler_annot_text_get_icon (poppler_annot); + EvAnnotationTextIcon retval; + + if (!icon) + return EV_ANNOTATION_TEXT_ICON_UNKNOWN; + + if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_NOTE) == 0) + retval = EV_ANNOTATION_TEXT_ICON_NOTE; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_COMMENT) == 0) + retval = EV_ANNOTATION_TEXT_ICON_COMMENT; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_KEY) == 0) + retval = EV_ANNOTATION_TEXT_ICON_KEY; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_HELP) == 0) + retval = EV_ANNOTATION_TEXT_ICON_HELP; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_NEW_PARAGRAPH) == 0) + retval = EV_ANNOTATION_TEXT_ICON_NEW_PARAGRAPH; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_PARAGRAPH) == 0) + retval = EV_ANNOTATION_TEXT_ICON_PARAGRAPH; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_INSERT) == 0) + retval = EV_ANNOTATION_TEXT_ICON_INSERT; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_CROSS) == 0) + retval = EV_ANNOTATION_TEXT_ICON_CROSS; + else if (strcmp (icon, POPPLER_ANNOT_TEXT_ICON_CIRCLE) == 0) + retval = EV_ANNOTATION_TEXT_ICON_CIRCLE; + else + retval = EV_ANNOTATION_TEXT_ICON_UNKNOWN; + + g_free (icon); + + return retval; +} + +static const gchar * +get_poppler_annot_text_icon (EvAnnotationTextIcon icon) +{ + switch (icon) { + case EV_ANNOTATION_TEXT_ICON_NOTE: + return POPPLER_ANNOT_TEXT_ICON_NOTE; + case EV_ANNOTATION_TEXT_ICON_COMMENT: + return POPPLER_ANNOT_TEXT_ICON_COMMENT; + case EV_ANNOTATION_TEXT_ICON_KEY: + return POPPLER_ANNOT_TEXT_ICON_KEY; + case EV_ANNOTATION_TEXT_ICON_HELP: + return POPPLER_ANNOT_TEXT_ICON_HELP; + case EV_ANNOTATION_TEXT_ICON_NEW_PARAGRAPH: + return POPPLER_ANNOT_TEXT_ICON_NEW_PARAGRAPH; + case EV_ANNOTATION_TEXT_ICON_PARAGRAPH: + return POPPLER_ANNOT_TEXT_ICON_PARAGRAPH; + case EV_ANNOTATION_TEXT_ICON_INSERT: + return POPPLER_ANNOT_TEXT_ICON_INSERT; + case EV_ANNOTATION_TEXT_ICON_CROSS: + return POPPLER_ANNOT_TEXT_ICON_CROSS; + case EV_ANNOTATION_TEXT_ICON_CIRCLE: + return POPPLER_ANNOT_TEXT_ICON_CIRCLE; + case EV_ANNOTATION_TEXT_ICON_UNKNOWN: + default: + return POPPLER_ANNOT_TEXT_ICON_NOTE; + } +} + static EvAnnotation * ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, EvPage *page) @@ -2541,10 +2556,11 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, ev_annot = ev_annotation_text_new (page); ev_annot_text = EV_ANNOTATION_TEXT (ev_annot); - ev_annot_text->is_open = poppler_annot_text_get_is_open (poppler_text); + ev_annotation_text_set_is_open (ev_annot_text, + poppler_annot_text_get_is_open (poppler_text)); + ev_annotation_text_set_icon (ev_annot_text, get_annot_text_icon (poppler_text)); } break; -#ifdef HAVE_POPPLER_ANNOT_FILE_ATTACHMENT_GET_ATTACHMENT case POPPLER_ANNOT_FILE_ATTACHMENT: { PopplerAnnotFileAttachment *poppler_annot_attachment; EvAnnotationAttachment *ev_annot_attachment; @@ -2576,7 +2592,6 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, g_object_unref (poppler_attachment); } break; -#endif /* HAVE_POPPLER_ANNOT_FILE_ATTACHMENT_GET_ATTACHMENT */ case POPPLER_ANNOT_LINK: case POPPLER_ANNOT_WIDGET: /* Ignore link and widgets annots since they are already handled */ @@ -2598,10 +2613,34 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, } if (ev_annot) { - ev_annot->contents = poppler_annot_get_contents (poppler_annot); - ev_annot->name = poppler_annot_get_name (poppler_annot); - ev_annot->modified = poppler_annot_get_modified (poppler_annot); - poppler_annot_color_to_gdk_color (poppler_annot, &ev_annot->color); + time_t utime; + gchar *modified; + gchar *contents; + gchar *name; + GdkColor color; + + contents = poppler_annot_get_contents (poppler_annot); + if (contents) { + ev_annotation_set_contents (ev_annot, contents); + g_free (contents); + } + + name = poppler_annot_get_name (poppler_annot); + if (name) { + ev_annotation_set_name (ev_annot, name); + g_free (name); + } + + modified = poppler_annot_get_modified (poppler_annot); + if (poppler_date_parse (modified, &utime)) { + ev_annotation_set_modified_from_time (ev_annot, utime); + } else { + ev_annotation_set_modified (ev_annot, modified); + } + g_free (modified); + + poppler_annot_color_to_gdk_color (poppler_annot, &color); + ev_annotation_set_color (ev_annot, &color); if (POPPLER_IS_ANNOT_MARKUP (poppler_annot)) { PopplerAnnotMarkup *markup; @@ -2627,13 +2666,10 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, g_object_set (ev_annot, "rectangle", &ev_rect, - "is_open", is_open, + "popup_is_open", is_open, "has_popup", TRUE, NULL); } else { - /* FIXME: Use poppler_annot_markup_has_popup() when - * new poppler is released. - */ g_object_set (ev_annot, "has_popup", FALSE, NULL); @@ -2654,13 +2690,14 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, return ev_annot; } -static GList * +static EvMappingList * pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annotations, EvPage *page) { GList *retval = NULL; PdfDocument *pdf_document; PopplerPage *poppler_page; + EvMappingList *mapping_list; GList *annots; GList *list; gdouble height; @@ -2668,12 +2705,20 @@ pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annota pdf_document = PDF_DOCUMENT (document_annotations); poppler_page = POPPLER_PAGE (page->backend_page); + + if (pdf_document->annots) { + mapping_list = (EvMappingList *)g_hash_table_lookup (pdf_document->annots, + GINT_TO_POINTER (page->index)); + if (mapping_list) + return ev_mapping_list_ref (mapping_list); + } + annots = poppler_page_get_annot_mapping (poppler_page); poppler_page_get_size (poppler_page, NULL, &height); for (list = annots; list; list = list->next) { PopplerAnnotMapping *mapping; - EvMapping *annot_mapping; + EvMapping *annot_mapping; EvAnnotation *ev_annot; mapping = (PopplerAnnotMapping *)list->data; @@ -2685,8 +2730,12 @@ pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annota i++; /* Make sure annot has a unique name */ - if (!ev_annot->name) - ev_annot->name = g_strdup_printf ("annot-%d-%d", page->index, i); + if (!ev_annotation_get_name (ev_annot)) { + gchar *name = g_strdup_printf ("annot-%d-%d", page->index, i); + + ev_annotation_set_name (ev_annot, name); + g_free (name); + } annot_mapping = g_new (EvMapping, 1); annot_mapping->area.x1 = mapping->area.x1; @@ -2705,13 +2754,137 @@ pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annota poppler_page_free_annot_mapping (annots); - return g_list_reverse (retval); + if (!retval) + return NULL; + + if (!pdf_document->annots) { + pdf_document->annots = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + (GDestroyNotify)NULL, + (GDestroyNotify)ev_mapping_list_unref); + } + + mapping_list = ev_mapping_list_new (page->index, g_list_reverse (retval), (GDestroyNotify)g_object_unref); + g_hash_table_insert (pdf_document->annots, + GINT_TO_POINTER (page->index), + ev_mapping_list_ref (mapping_list)); + + return mapping_list; +} + +static gboolean +pdf_document_annotations_document_is_modified (EvDocumentAnnotations *document_annotations) +{ + return PDF_DOCUMENT (document_annotations)->annots_modified; } static void -pdf_document_annotations_annotation_set_contents (EvDocumentAnnotations *document, - EvAnnotation *annot, - const gchar *contents) +pdf_document_annotations_add_annotation (EvDocumentAnnotations *document_annotations, + EvAnnotation *annot, + EvRectangle *rect) +{ + PopplerAnnot *poppler_annot; + PdfDocument *pdf_document; + EvPage *page; + PopplerPage *poppler_page; + GList *list = NULL; + EvMappingList *mapping_list; + EvMapping *annot_mapping; + PopplerRectangle poppler_rect; + gdouble height; + PopplerColor poppler_color; + GdkColor color; + time_t utime; + gchar *modified; + gchar *name; + + pdf_document = PDF_DOCUMENT (document_annotations); + page = ev_annotation_get_page (annot); + poppler_page = POPPLER_PAGE (page->backend_page); + + poppler_page_get_size (poppler_page, NULL, &height); + poppler_rect.x1 = rect->x1; + poppler_rect.x2 = rect->x2; + poppler_rect.y1 = height - rect->y2; + poppler_rect.y2 = height - rect->y1; + poppler_annot = poppler_annot_text_new (pdf_document->document, &poppler_rect); + + ev_annotation_get_color (annot, &color); + poppler_color.red = color.red; + poppler_color.green = color.green; + poppler_color.blue = color.blue; + poppler_annot_set_color (poppler_annot, &poppler_color); + + if (EV_IS_ANNOTATION_MARKUP (annot)) { + EvAnnotationMarkup *markup = EV_ANNOTATION_MARKUP (annot); + const gchar *label; + + if (ev_annotation_markup_has_popup (markup)) { + EvRectangle popup_rect; + + ev_annotation_markup_get_rectangle (markup, &popup_rect); + poppler_rect.x1 = popup_rect.x1; + poppler_rect.x2 = popup_rect.x2; + poppler_rect.y1 = height - popup_rect.y2; + poppler_rect.y2 = height - popup_rect.y1; + poppler_annot_markup_set_popup (POPPLER_ANNOT_MARKUP (poppler_annot), &poppler_rect); + poppler_annot_markup_set_popup_is_open (POPPLER_ANNOT_MARKUP (poppler_annot), + ev_annotation_markup_get_popup_is_open (markup)); + } + + label = ev_annotation_markup_get_label (markup); + if (label) + poppler_annot_markup_set_label (POPPLER_ANNOT_MARKUP (poppler_annot), label); + } + + if (EV_IS_ANNOTATION_TEXT (annot)) { + EvAnnotationText *text = EV_ANNOTATION_TEXT (annot); + EvAnnotationTextIcon icon; + + icon = ev_annotation_text_get_icon (text); + poppler_annot_text_set_icon (POPPLER_ANNOT_TEXT (poppler_annot), + get_poppler_annot_text_icon (icon)); + } + poppler_page_add_annot (poppler_page, poppler_annot); + + annot_mapping = g_new (EvMapping, 1); + annot_mapping->area = *rect; + annot_mapping->data = annot; + g_object_set_data_full (G_OBJECT (annot), + "poppler-annot", + g_object_ref (poppler_annot), + (GDestroyNotify) g_object_unref); + + if (pdf_document->annots) { + mapping_list = (EvMappingList *)g_hash_table_lookup (pdf_document->annots, + GINT_TO_POINTER (page->index)); + list = ev_mapping_list_get_list (mapping_list); + name = g_strdup_printf ("annot-%d-%d", page->index, g_list_length (list) + 1); + ev_annotation_set_name (annot, name); + g_free (name); + list = g_list_append (list, annot_mapping); + } else { + pdf_document->annots = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + (GDestroyNotify)NULL, + (GDestroyNotify)ev_mapping_list_unref); + name = g_strdup_printf ("annot-%d-0", page->index); + ev_annotation_set_name (annot, name); + g_free (name); + list = g_list_append (list, annot_mapping); + mapping_list = ev_mapping_list_new (page->index, list, (GDestroyNotify)g_object_unref); + g_hash_table_insert (pdf_document->annots, + GINT_TO_POINTER (page->index), + ev_mapping_list_ref (mapping_list)); + } + + pdf_document->annots_modified = TRUE; +} + +static void +pdf_document_annotations_save_annotation (EvDocumentAnnotations *document_annotations, + EvAnnotation *annot, + EvAnnotationsSaveMask mask) { PopplerAnnot *poppler_annot; @@ -2719,15 +2892,59 @@ pdf_document_annotations_annotation_set_contents (EvDocumentAnnotations *documen if (!poppler_annot) return; - poppler_annot_set_contents (poppler_annot, contents); - PDF_DOCUMENT (document)->modified = TRUE; + if (mask & EV_ANNOTATIONS_SAVE_CONTENTS) + poppler_annot_set_contents (poppler_annot, + ev_annotation_get_contents (annot)); + + if (mask & EV_ANNOTATIONS_SAVE_COLOR) { + PopplerColor color; + GdkColor ev_color; + + ev_annotation_get_color (annot, &ev_color); + color.red = ev_color.red; + color.green = ev_color.green; + color.blue = ev_color.blue; + poppler_annot_set_color (poppler_annot, &color); + } + + if (EV_IS_ANNOTATION_MARKUP (annot)) { + EvAnnotationMarkup *ev_markup = EV_ANNOTATION_MARKUP (annot); + PopplerAnnotMarkup *markup = POPPLER_ANNOT_MARKUP (poppler_annot); + + if (mask & EV_ANNOTATIONS_SAVE_LABEL) + poppler_annot_markup_set_label (markup, ev_annotation_markup_get_label (ev_markup)); + if (mask & EV_ANNOTATIONS_SAVE_OPACITY) + poppler_annot_markup_set_opacity (markup, ev_annotation_markup_get_opacity (ev_markup)); + if (mask & EV_ANNOTATIONS_SAVE_POPUP_IS_OPEN) + poppler_annot_markup_set_popup_is_open (markup, ev_annotation_markup_get_popup_is_open (ev_markup)); + } + + if (EV_IS_ANNOTATION_TEXT (annot)) { + EvAnnotationText *ev_text = EV_ANNOTATION_TEXT (annot); + PopplerAnnotText *text = POPPLER_ANNOT_TEXT (poppler_annot); + + if (mask & EV_ANNOTATIONS_SAVE_TEXT_IS_OPEN) { + poppler_annot_text_set_is_open (text, + ev_annotation_text_get_is_open (ev_text)); + } + if (mask & EV_ANNOTATIONS_SAVE_TEXT_ICON) { + EvAnnotationTextIcon icon; + + icon = ev_annotation_text_get_icon (ev_text); + poppler_annot_text_set_icon (text, get_poppler_annot_text_icon (icon)); + } + } + + PDF_DOCUMENT (document_annotations)->annots_modified = TRUE; } static void -pdf_document_document_annotations_iface_init (EvDocumentAnnotationsIface *iface) +pdf_document_document_annotations_iface_init (EvDocumentAnnotationsInterface *iface) { iface->get_annotations = pdf_document_annotations_get_annotations; - iface->annotation_set_contents = pdf_document_annotations_annotation_set_contents; + iface->document_is_modified = pdf_document_annotations_document_is_modified; + iface->add_annotation = pdf_document_annotations_add_annotation; + iface->save_annotation = pdf_document_annotations_save_annotation; } /* Attachments */ @@ -2841,7 +3058,7 @@ pdf_document_attachments_has_attachments (EvDocumentAttachments *document) } static void -pdf_document_document_attachments_iface_init (EvDocumentAttachmentsIface *iface) +pdf_document_document_attachments_iface_init (EvDocumentAttachmentsInterface *iface) { iface->has_attachments = pdf_document_attachments_has_attachments; iface->get_attachments = pdf_document_attachments_get_attachments; @@ -2882,11 +3099,12 @@ build_layers_tree (PdfDocument *pdf_document, markup = g_markup_escape_text (poppler_layer_get_title (layer), -1); visible = poppler_layer_is_visible (layer); rb_group = poppler_layer_get_radio_button_group_id (layer); - pdf_document->layers = g_list_append (pdf_document->layers, - g_object_ref (layer)); - ev_layer = ev_layer_new (g_list_length (pdf_document->layers) - 1, - poppler_layer_is_parent (layer), + ev_layer = ev_layer_new (poppler_layer_is_parent (layer), rb_group); + g_object_set_data_full (G_OBJECT (ev_layer), + "poppler-layer", + g_object_ref (layer), + (GDestroyNotify) g_object_unref); } else { gchar *title; @@ -2944,34 +3162,37 @@ static void pdf_document_layers_show_layer (EvDocumentLayers *document, EvLayer *layer) { - PdfDocument *pdf_document = PDF_DOCUMENT (document); - guint layer_id = ev_layer_get_id (layer); + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerLayer *poppler_layer; - poppler_layer_show (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); + poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer")); + poppler_layer_show (poppler_layer); } static void pdf_document_layers_hide_layer (EvDocumentLayers *document, EvLayer *layer) { - PdfDocument *pdf_document = PDF_DOCUMENT (document); - guint layer_id = ev_layer_get_id (layer); + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerLayer *poppler_layer; - poppler_layer_hide (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); + poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer")); + poppler_layer_hide (poppler_layer); } static gboolean pdf_document_layers_layer_is_visible (EvDocumentLayers *document, EvLayer *layer) { - PdfDocument *pdf_document = PDF_DOCUMENT (document); - guint layer_id = ev_layer_get_id (layer); + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerLayer *poppler_layer; - return poppler_layer_is_visible (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); + poppler_layer = POPPLER_LAYER (g_object_get_data (G_OBJECT (layer), "poppler-layer")); + return poppler_layer_is_visible (poppler_layer); } static void -pdf_document_document_layers_iface_init (EvDocumentLayersIface *iface) +pdf_document_document_layers_iface_init (EvDocumentLayersInterface *iface) { iface->has_layers = pdf_document_layers_has_layers; iface->get_layers = pdf_document_layers_get_layers;