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=841706ead130de392cbe9b01f7a497f545dcf80d;hb=0b6b3dff626d31a368ef9a95f8ed73b404eec9bf;hp=04f4c650a22f9a4a12088ec3bdf67dfaeacd53d8;hpb=31a1e800e5d6b24d8833ba28746b7ff6f2fbe6a9;p=evince.git diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index 04f4c650..841706ea 100644 --- a/backend/pdf/ev-poppler.cc +++ b/backend/pdf/ev-poppler.cc @@ -31,7 +31,7 @@ #ifdef HAVE_CAIRO_PS #include #endif -#include +#include #include "ev-poppler.h" #include "ev-file-exporter.h" @@ -44,6 +44,7 @@ #include "ev-document-thumbnails.h" #include "ev-document-transition.h" #include "ev-document-forms.h" +#include "ev-document-layers.h" #include "ev-selection.h" #include "ev-transition-effect.h" #include "ev-attachment.h" @@ -98,6 +99,8 @@ struct _PdfDocument PdfDocumentSearch *search; PdfPrintContext *print_ctx; + + GList *layers; }; static void pdf_document_document_iface_init (EvDocumentIface *iface); @@ -107,6 +110,7 @@ static void pdf_document_document_links_iface_init (EvDocumentLinksIface 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); 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); @@ -138,6 +142,8 @@ EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document, pdf_document_document_forms_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS, pdf_document_document_fonts_iface_init); + EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LAYERS, + pdf_document_document_layers_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND, pdf_document_find_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER, @@ -196,6 +202,11 @@ 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); } @@ -217,6 +228,7 @@ static void convert_error (GError *poppler_error, GError **error) { + g_return_if_fail (poppler_error != NULL); if (poppler_error == NULL) return; @@ -228,12 +240,12 @@ convert_error (GError *poppler_error, else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED) code = EV_DOCUMENT_ERROR_ENCRYPTED; + g_set_error_literal (error, + EV_DOCUMENT_ERROR, + code, + poppler_error->message); - g_set_error (error, - EV_DOCUMENT_ERROR, - code, - poppler_error->message, - NULL); + g_error_free (poppler_error); } else { g_propagate_error (error, poppler_error); } @@ -872,7 +884,7 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, poppler_page_get_size (poppler_page, NULL, &height); ev_dest = ev_link_dest_new_xyz (dest->page_num - 1, dest->left, - height - dest->top, + height - MIN (height, dest->top), dest->zoom, dest->change_left, dest->change_top, @@ -891,7 +903,7 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, MAX (0, dest->page_num - 1)); poppler_page_get_size (poppler_page, NULL, &height); ev_dest = ev_link_dest_new_fith (dest->page_num - 1, - height - dest->top, + height - MIN (height, dest->top), dest->change_top); g_object_unref (poppler_page); } @@ -910,9 +922,9 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, poppler_page_get_size (poppler_page, NULL, &height); ev_dest = ev_link_dest_new_fitr (dest->page_num - 1, dest->left, - height - dest->bottom, + height - MIN (height, dest->bottom), dest->right, - height - dest->top); + height - MIN (height, dest->top)); g_object_unref (poppler_page); } break; @@ -1214,7 +1226,6 @@ GdkPixbuf * pdf_document_images_get_image (EvDocumentImages *document_images, EvImage *image) { -#ifdef HAVE_POPPLER_PAGE_GET_IMAGE PdfDocument *pdf_document; PopplerPage *poppler_page; cairo_surface_t *surface; @@ -1233,9 +1244,6 @@ pdf_document_images_get_image (EvDocumentImages *document_images, g_object_unref (poppler_page); return retval; -#else - return GDK_PIXBUF (g_object_ref (ev_image_get_pixbuf (image))); -#endif /* HAVE_POPPLER_PAGE_GET_IMAGE */ } static void @@ -1338,7 +1346,7 @@ pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnail has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height); - if (!has_thumb) { + if (!has_thumb || *width <= 0 || *height <= 0) { double page_width, page_height; poppler_page_get_size (poppler_page, &page_width, &page_height); @@ -1364,195 +1372,42 @@ pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface) } -static gboolean -pdf_document_search_idle_callback (void *data) -{ - PdfDocumentSearch *search = (PdfDocumentSearch*) data; - PdfDocument *pdf_document = search->document; - int n_pages; - GList *matches; - PopplerPage *page; - - page = poppler_document_get_page (search->document->document, - search->search_page); - - ev_document_doc_mutex_lock (); - matches = poppler_page_find_text (page, search->text); - ev_document_doc_mutex_unlock (); - - g_object_unref (page); - - search->pages[search->search_page] = matches; - ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document), - search->search_page); - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document)); - search->search_page += 1; - if (search->search_page == n_pages) { - /* wrap around */ - search->search_page = 0; - } - - if (search->search_page != search->start_page) { - return TRUE; - } - - /* We're done. */ - search->idle = 0; /* will return FALSE to remove */ - return FALSE; -} - - -static PdfDocumentSearch * -pdf_document_search_new (PdfDocument *pdf_document, - int start_page, - const char *text) -{ - PdfDocumentSearch *search; - int n_pages; - int i; - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document)); - - search = g_new0 (PdfDocumentSearch, 1); - - search->text = g_strdup (text); - search->pages = g_new0 (GList *, n_pages); - search->document = pdf_document; - - /* We add at low priority so the progress bar repaints */ - search->idle = g_idle_add_full (G_PRIORITY_LOW, - pdf_document_search_idle_callback, - search, - NULL); - - search->start_page = start_page; - search->search_page = start_page; - - return search; -} - -static void -pdf_document_find_begin (EvDocumentFind *document, - int page, - const char *search_string, - gboolean case_sensitive) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (document); - - /* FIXME handle case_sensitive (right now XPDF - * code is always case insensitive for ASCII - * and case sensitive for all other languaages) - */ - - if (pdf_document->search && - strcmp (search_string, pdf_document->search->text) == 0) - return; - - if (pdf_document->search) - pdf_document_search_free (pdf_document->search); - - pdf_document->search = pdf_document_search_new (pdf_document, - page, - search_string); -} - -static int -pdf_document_find_get_n_results (EvDocumentFind *document_find, int page) -{ - PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; - - if (search) { - return g_list_length (search->pages[page]); - } else { - return 0; - } -} - -static gboolean -pdf_document_find_get_result (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle) +static GList * +pdf_document_find_find_text (EvDocumentFind *document_find, + EvPage *page, + const gchar *text, + gboolean case_sensitive) { - PdfDocument *pdf_document = PDF_DOCUMENT (document_find); - PdfDocumentSearch *search = pdf_document->search; + GList *matches, *l; PopplerPage *poppler_page; - PopplerRectangle *r; - double height; - - if (search == NULL) - return FALSE; + gdouble height; + + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); + g_return_val_if_fail (text != NULL, NULL); - r = (PopplerRectangle *) g_list_nth_data (search->pages[page], - n_result); - if (r == NULL) - return FALSE; + poppler_page = POPPLER_PAGE (page->backend_page); + + matches = poppler_page_find_text (poppler_page, text); + if (!matches) + return NULL; - poppler_page = poppler_document_get_page (pdf_document->document, page); poppler_page_get_size (poppler_page, NULL, &height); - rectangle->x1 = r->x1; - rectangle->y1 = height - r->y2; - rectangle->x2 = r->x2; - rectangle->y2 = height - r->y1; - g_object_unref (poppler_page); - - return TRUE; -} - -static int -pdf_document_find_page_has_results (EvDocumentFind *document_find, - int page) -{ - PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; - - return search && search->pages[page] != NULL; -} - -static double -pdf_document_find_get_progress (EvDocumentFind *document_find) -{ - PdfDocumentSearch *search; - int n_pages, pages_done; - - search = PDF_DOCUMENT (document_find)->search; + for (l = matches; l && l->data; l = g_list_next (l)) { + PopplerRectangle *rect = (PopplerRectangle *)l->data; + gdouble tmp; - if (search == NULL) { - return 0; - } - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find)); - if (search->search_page > search->start_page) { - pages_done = search->search_page - search->start_page + 1; - } else if (search->search_page == search->start_page) { - pages_done = n_pages; - } else { - pages_done = n_pages - search->start_page + search->search_page; - } - - return pages_done / (double) n_pages; -} - -static void -pdf_document_find_cancel (EvDocumentFind *document) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (document); - - if (pdf_document->search) { - pdf_document_search_free (pdf_document->search); - pdf_document->search = NULL; + tmp = rect->y1; + rect->y1 = height - rect->y2; + rect->y2 = height - tmp; } + + return matches; } static void pdf_document_find_iface_init (EvDocumentFindIface *iface) { - iface->begin = pdf_document_find_begin; - iface->get_n_results = pdf_document_find_get_n_results; - iface->get_result = pdf_document_find_get_result; - iface->page_has_results = pdf_document_find_page_has_results; - iface->get_progress = pdf_document_find_get_progress; - iface->cancel = pdf_document_find_cancel; + iface->find_text = pdf_document_find_find_text; } static void @@ -1821,11 +1676,9 @@ pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter) EV_FILE_EXPORTER_CAN_SCALE | #ifdef HAVE_CAIRO_PRINT #ifdef HAVE_POPPLER_PAGE_RENDER -#if GTK_CHECK_VERSION (2, 11, 1) EV_FILE_EXPORTER_CAN_NUMBER_UP | #endif #endif -#endif #ifdef HAVE_CAIRO_PDF #ifdef HAVE_POPPLER_PAGE_RENDER @@ -2462,3 +2315,156 @@ pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface) iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text; } +/* Layers */ +static gboolean +pdf_document_layers_has_layers (EvDocumentLayers *document) +{ +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerLayersIter *iter; + + iter = poppler_layers_iter_new (pdf_document->document); + if (!iter) + return FALSE; + poppler_layers_iter_free (iter); + + return TRUE; +#else + return FALSE; +#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ +} + +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW +static void +build_layers_tree (PdfDocument *pdf_document, + GtkTreeModel *model, + GtkTreeIter *parent, + PopplerLayersIter *iter) +{ + do { + GtkTreeIter tree_iter; + PopplerLayersIter *child; + PopplerLayer *layer; + EvLayer *ev_layer = NULL; + gboolean visible; + gchar *markup; + gint rb_group = 0; + + layer = poppler_layers_iter_get_layer (iter); + if (layer) { + 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), + rb_group); + } else { + gchar *title; + + title = poppler_layers_iter_get_title (iter); + markup = g_markup_escape_text (title, -1); + g_free (title); + + visible = FALSE; + layer = NULL; + } + + gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent); + gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter, + EV_DOCUMENT_LAYERS_COLUMN_TITLE, markup, + EV_DOCUMENT_LAYERS_COLUMN_VISIBLE, visible, + EV_DOCUMENT_LAYERS_COLUMN_ENABLED, TRUE, /* FIXME */ + EV_DOCUMENT_LAYERS_COLUMN_SHOWTOGGLE, (layer != NULL), + EV_DOCUMENT_LAYERS_COLUMN_RBGROUP, rb_group, + EV_DOCUMENT_LAYERS_COLUMN_LAYER, ev_layer, + -1); + if (ev_layer) + g_object_unref (ev_layer); + g_free (markup); + + child = poppler_layers_iter_get_child (iter); + if (child) + build_layers_tree (pdf_document, model, &tree_iter, child); + poppler_layers_iter_free (child); + } while (poppler_layers_iter_next (iter)); +} +#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ + +static GtkTreeModel * +pdf_document_layers_get_layers (EvDocumentLayers *document) +{ + GtkTreeModel *model = NULL; +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerLayersIter *iter; + + iter = poppler_layers_iter_new (pdf_document->document); + if (iter) { + model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LAYERS_N_COLUMNS, + G_TYPE_STRING, /* TITLE */ + G_TYPE_OBJECT, /* LAYER */ + G_TYPE_BOOLEAN, /* VISIBLE */ + G_TYPE_BOOLEAN, /* ENABLED */ + G_TYPE_BOOLEAN, /* SHOWTOGGLE */ + G_TYPE_INT); /* RBGROUP */ + build_layers_tree (pdf_document, model, NULL, iter); + poppler_layers_iter_free (iter); + } + +#endif + return model; +} + +static void +pdf_document_layers_show_layer (EvDocumentLayers *document, + EvLayer *layer) +{ +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW + PdfDocument *pdf_document = PDF_DOCUMENT (document); + guint layer_id = ev_layer_get_id (layer); + + poppler_layer_show (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); +#else + return; +#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ +} + +static void +pdf_document_layers_hide_layer (EvDocumentLayers *document, + EvLayer *layer) +{ +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW + PdfDocument *pdf_document = PDF_DOCUMENT (document); + guint layer_id = ev_layer_get_id (layer); + + poppler_layer_hide (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); +#else + return; +#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ +} + +static gboolean +pdf_document_layers_layer_is_visible (EvDocumentLayers *document, + EvLayer *layer) +{ +#ifdef HAVE_POPPLER_LAYERS_ITER_NEW + PdfDocument *pdf_document = PDF_DOCUMENT (document); + guint layer_id = ev_layer_get_id (layer); + + return poppler_layer_is_visible (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); +#else + return FALSE; +#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ +} + +static void +pdf_document_document_layers_iface_init (EvDocumentLayersIface *iface) +{ + iface->has_layers = pdf_document_layers_has_layers; + iface->get_layers = pdf_document_layers_get_layers; + iface->show_layer = pdf_document_layers_show_layer; + iface->hide_layer = pdf_document_layers_hide_layer; + iface->layer_is_visible = pdf_document_layers_layer_is_visible; +}