X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=pdf%2Fev-poppler.cc;h=0f9a3562c2dde199d2ff3a763ba2ade5916be8ff;hb=274f17472f798aa469fe6089291efa5379de157c;hp=ac602b0452a7f3a45f96cdab1d46d3cd3e8070fb;hpb=cf6c30c93ee2c79e90200b2316587aeb12dc2ee2;p=evince.git diff --git a/pdf/ev-poppler.cc b/pdf/ev-poppler.cc index ac602b04..0f9a3562 100644 --- a/pdf/ev-poppler.cc +++ b/pdf/ev-poppler.cc @@ -23,22 +23,17 @@ #include #include #include +#include #include "ev-poppler.h" #include "ev-ps-exporter.h" #include "ev-document-find.h" #include "ev-document-misc.h" #include "ev-document-links.h" +#include "ev-document-fonts.h" #include "ev-document-security.h" #include "ev-document-thumbnails.h" - -enum { - PROP_0, - PROP_TITLE -}; - - typedef struct { PdfDocument *document; char *text; @@ -61,6 +56,12 @@ struct _PdfDocument PopplerPSFile *ps_file; gchar *password; + PopplerOrientation orientation; + + PopplerFontInfo *font_info; + PopplerFontsIter *fonts_iter; + int fonts_scanned_pages; + PdfDocumentSearch *search; }; @@ -68,6 +69,7 @@ static void pdf_document_document_iface_init (EvDocumentIface 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_fonts_iface_init (EvDocumentFontsIface *iface); static void pdf_document_find_iface_init (EvDocumentFindIface *iface); static void pdf_document_ps_exporter_iface_init (EvPSExporterIface *iface); static void pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails, @@ -88,46 +90,45 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, pdf_document_document_thumbnails_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS, pdf_document_document_links_iface_init); + G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS, + pdf_document_document_fonts_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND, pdf_document_find_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER, pdf_document_ps_exporter_iface_init); }); - static void -pdf_document_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (object); - - switch (prop_id) - { - case PROP_TITLE: - if (pdf_document->document == NULL) - g_value_set_string (value, NULL); - else - g_object_get_property (G_OBJECT (pdf_document->document), "title", value); - break; +pdf_document_dispose (GObject *object) +{ + PdfDocument *pdf_document = PDF_DOCUMENT(object); + + if (pdf_document->document) { + g_object_unref (pdf_document->document); + } + + if (pdf_document->font_info) { + poppler_font_info_free (pdf_document->font_info); + } + + if (pdf_document->fonts_iter) { + poppler_fonts_iter_free (pdf_document->fonts_iter); } } static void pdf_document_class_init (PdfDocumentClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->get_property = pdf_document_get_property; + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); - g_object_class_override_property (gobject_class, PROP_TITLE, "title"); + g_object_class->dispose = pdf_document_dispose; } static void pdf_document_init (PdfDocument *pdf_document) { pdf_document->password = NULL; + pdf_document->orientation = POPPLER_ORIENTATION_PORTRAIT; } static void @@ -175,6 +176,24 @@ pdf_document_save (EvDocument *document, return retval; } +static PopplerOrientation +get_document_orientation (PdfDocument *pdf_document) +{ +#ifdef POPPLER_ORIENTATION + PopplerPage *page; + + /* Should prolly be smarter here and check more than first page */ + page = poppler_document_get_page (pdf_document->document, 0); + if (page) { + return poppler_page_get_orientation (page); + } else { + return POPPLER_ORIENTATION_PORTRAIT; + } +#else + return POPPLER_ORIENTATION_PORTRAIT; +#endif +} + static gboolean pdf_document_load (EvDocument *document, const char *uri, @@ -191,6 +210,8 @@ pdf_document_load (EvDocument *document, return FALSE; } + pdf_document->orientation = get_document_orientation (pdf_document); + return TRUE; } @@ -206,11 +227,11 @@ pdf_document_get_page_size (EvDocument *document, double *width, double *height) { + PdfDocument *pdf_document = PDF_DOCUMENT (document); PopplerPage *poppler_page; - poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document, - page); - + poppler_page = poppler_document_get_page (pdf_document->document, page); + poppler_page_set_orientation (poppler_page, pdf_document->orientation); poppler_page_get_size (poppler_page, width, height); } @@ -224,7 +245,7 @@ pdf_document_get_page_label (EvDocument *document, poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document, page); - g_object_get (poppler_page, + g_object_get (G_OBJECT (poppler_page), "label", &label, NULL); @@ -284,10 +305,11 @@ pdf_document_render_pixbuf (EvDocument *document, pdf_document = PDF_DOCUMENT (document); poppler_page = poppler_document_get_page (pdf_document->document, page); + poppler_page_set_orientation (poppler_page, pdf_document->orientation); poppler_page_get_size (poppler_page, &width_points, &height_points); - width = (int) ceil (width_points * scale); - height = (int) ceil (height_points * scale); + width = (int) ((width_points * scale) + 0.5); + height = (int) ((height_points * scale) + 0.5); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, @@ -324,6 +346,149 @@ pdf_document_set_password (EvDocumentSecurity *document_security, document->password = g_strdup (password); } +static gboolean +pdf_document_can_get_text (EvDocument *document) +{ + return TRUE; +} + +static EvDocumentInfo * +pdf_document_get_info (EvDocument *document) +{ + EvDocumentInfo *info; + PopplerPageLayout layout; + PopplerPageMode mode; + PopplerViewerPreferences view_prefs; + PopplerPermissions permissions; + + info = g_new0 (EvDocumentInfo, 1); + + info->fields_mask = EV_DOCUMENT_INFO_TITLE | + EV_DOCUMENT_INFO_FORMAT | + EV_DOCUMENT_INFO_AUTHOR | + EV_DOCUMENT_INFO_SUBJECT | + EV_DOCUMENT_INFO_KEYWORDS | + EV_DOCUMENT_INFO_LAYOUT | + EV_DOCUMENT_INFO_START_MODE | + EV_DOCUMENT_INFO_PERMISSIONS | + EV_DOCUMENT_INFO_UI_HINTS | + EV_DOCUMENT_INFO_CREATOR | + EV_DOCUMENT_INFO_PRODUCER | + EV_DOCUMENT_INFO_CREATION_DATE | + EV_DOCUMENT_INFO_MOD_DATE | + EV_DOCUMENT_INFO_LINEARIZED | + EV_DOCUMENT_INFO_N_PAGES | + EV_DOCUMENT_INFO_SECURITY; + + + g_object_get (PDF_DOCUMENT (document)->document, + "title", &(info->title), + "format", &(info->format), + "author", &(info->author), + "subject", &(info->subject), + "keywords", &(info->keywords), + "page-mode", &mode, + "page-layout", &layout, + "viewer-preferences", &view_prefs, + "permissions", &permissions, + "creator", &(info->creator), + "producer", &(info->producer), + "creation-date", &(info->creation_date), + "mod-date", &(info->modified_date), + "linearized", &(info->linearized), + NULL); + + switch (layout) { + case POPPLER_PAGE_LAYOUT_SINGLE_PAGE: + info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE; + break; + case POPPLER_PAGE_LAYOUT_ONE_COLUMN: + info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN; + break; + case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT: + info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT; + break; + case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT: + info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT; + case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT: + info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT; + break; + case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT: + info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT; + break; + default: + break; + } + + switch (mode) { + case POPPLER_PAGE_MODE_NONE: + info->mode = EV_DOCUMENT_MODE_NONE; + break; + case POPPLER_PAGE_MODE_USE_THUMBS: + info->mode = EV_DOCUMENT_MODE_USE_THUMBS; + break; + case POPPLER_PAGE_MODE_USE_OC: + info->mode = EV_DOCUMENT_MODE_USE_OC; + break; + case POPPLER_PAGE_MODE_FULL_SCREEN: + info->mode = EV_DOCUMENT_MODE_FULL_SCREEN; + break; + case POPPLER_PAGE_MODE_USE_ATTACHMENTS: + info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS; + default: + break; + } + + info->ui_hints = 0; + if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE; + } + if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) { + info->ui_hints |= EV_DOCUMENT_UI_HINT_DIRECTION_RTL; + } + + info->permissions = 0; + if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) { + info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT; + } + if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) { + info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY; + } + if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) { + info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY; + } + if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) { + info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES; + } + + info->n_pages = ev_document_get_n_pages (document); + + if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) { + /* translators: this is the document security state */ + info->security = g_strdup (_("Yes")); + } else { + /* translators: this is the document security state */ + info->security = g_strdup (_("No")); + } + + return info; +} + static char * pdf_document_get_text (EvDocument *document, int page, EvRectangle *rect) { @@ -341,11 +506,57 @@ pdf_document_get_text (EvDocument *document, int page, EvRectangle *rect) r.x2 = rect->x2; r.y2 = height - rect->y1; - g_print ("%f %f %f %f\n", r.x1, r.y1, r.x2, r.y2); - return poppler_page_get_text (poppler_page, &r); } +static EvOrientation +pdf_document_get_orientation (EvDocument *document) +{ + EvOrientation result; + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + switch (pdf_document->orientation) { + case POPPLER_ORIENTATION_PORTRAIT: + result = EV_ORIENTATION_PORTRAIT; + break; + case POPPLER_ORIENTATION_LANDSCAPE: + result = EV_ORIENTATION_LANDSCAPE; + break; + case POPPLER_ORIENTATION_UPSIDEDOWN: + result = EV_ORIENTATION_UPSIDEDOWN; + break; + case POPPLER_ORIENTATION_SEASCAPE: + result = EV_ORIENTATION_SEASCAPE; + break; + } + + return result; +} + +static void +pdf_document_set_orientation (EvDocument *document, EvOrientation orientation) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + PopplerOrientation poppler_orientation; + + switch (orientation) { + case EV_ORIENTATION_PORTRAIT: + poppler_orientation = POPPLER_ORIENTATION_PORTRAIT; + break; + case EV_ORIENTATION_LANDSCAPE: + poppler_orientation = POPPLER_ORIENTATION_LANDSCAPE; + break; + case EV_ORIENTATION_UPSIDEDOWN: + poppler_orientation = POPPLER_ORIENTATION_UPSIDEDOWN; + break; + case EV_ORIENTATION_SEASCAPE: + poppler_orientation = POPPLER_ORIENTATION_SEASCAPE; + break; + } + + pdf_document->orientation = poppler_orientation; +} + static void pdf_document_document_iface_init (EvDocumentIface *iface) { @@ -357,6 +568,10 @@ pdf_document_document_iface_init (EvDocumentIface *iface) iface->get_links = pdf_document_get_links; iface->render_pixbuf = pdf_document_render_pixbuf; iface->get_text = pdf_document_get_text; + iface->can_get_text = pdf_document_can_get_text; + iface->get_info = pdf_document_get_info; + iface->set_orientation = pdf_document_set_orientation; + iface->get_orientation = pdf_document_get_orientation; }; static void @@ -366,6 +581,79 @@ pdf_document_security_iface_init (EvDocumentSecurityIface *iface) iface->set_password = pdf_document_set_password; } +static gdouble +pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts); + int n_pages; + + n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document)); + + return (double)pdf_document->fonts_scanned_pages / (double)n_pages; +} + +static gboolean +pdf_document_fonts_scan (EvDocumentFonts *document_fonts, + int n_pages) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts); + gboolean result; + + g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE); + + if (pdf_document->font_info == NULL) { + pdf_document->font_info = poppler_font_info_new (pdf_document->document); + } + + if (pdf_document->fonts_iter) { + poppler_fonts_iter_free (pdf_document->fonts_iter); + } + + pdf_document->fonts_scanned_pages += n_pages; + + result = poppler_font_info_scan (pdf_document->font_info, n_pages, + &pdf_document->fonts_iter); + if (!result) { + pdf_document->fonts_scanned_pages = 0; + poppler_font_info_free (pdf_document->font_info); + pdf_document->font_info = NULL; + } + + return result; +} + +static void +pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts, + GtkTreeModel *model) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts); + PopplerFontsIter *iter = pdf_document->fonts_iter; + + g_return_if_fail (PDF_IS_DOCUMENT (document_fonts)); + + if (iter) { + do { + GtkTreeIter list_iter; + PopplerIndexIter *child; + const char *name; + + name = poppler_fonts_iter_get_name (iter); + gtk_list_store_append (GTK_LIST_STORE (model), &list_iter); + gtk_list_store_set (GTK_LIST_STORE (model), &list_iter, + EV_DOCUMENT_FONTS_COLUMN_NAME, name, + -1); + } while (poppler_fonts_iter_next (iter)); + } +} + +static void +pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface) +{ + iface->fill_model = pdf_document_fonts_fill_model; + iface->scan = pdf_document_fonts_scan; + iface->get_progress = pdf_document_fonts_get_progress; +} + static gboolean pdf_document_links_has_document_links (EvDocumentLinks *document_links) { @@ -401,7 +689,6 @@ ev_link_from_action (PopplerAction *action) return link; } - static void build_tree (PdfDocument *pdf_document, GtkTreeModel *model, @@ -414,8 +701,10 @@ build_tree (PdfDocument *pdf_document, PopplerIndexIter *child; PopplerAction *action; EvLink *link; + gboolean expand; action = poppler_index_iter_get_action (iter); + expand = poppler_index_iter_is_open (iter); if (action) { gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent); link = ev_link_from_action (action); @@ -424,6 +713,7 @@ build_tree (PdfDocument *pdf_document, gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter, EV_DOCUMENT_LINKS_COLUMN_MARKUP, ev_link_get_title (link), EV_DOCUMENT_LINKS_COLUMN_LINK, link, + EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand, -1); child = poppler_index_iter_get_child (iter); if (child) @@ -444,20 +734,19 @@ pdf_document_links_get_links_model (EvDocumentLinks *document_links) g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL); iter = poppler_index_iter_new (pdf_document->document); - /* Create the model iff we have items*/ + /* Create the model if we have items*/ if (iter != NULL) { model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS, G_TYPE_STRING, - G_TYPE_POINTER); + G_TYPE_POINTER, + G_TYPE_BOOLEAN); build_tree (pdf_document, model, NULL, iter); poppler_index_iter_free (iter); } - return model; } - static void pdf_document_document_links_iface_init (EvDocumentLinksIface *iface) { @@ -465,7 +754,6 @@ pdf_document_document_links_iface_init (EvDocumentLinksIface *iface) iface->get_links_model = pdf_document_links_get_links_model; } - static GdkPixbuf * make_thumbnail_for_size (PdfDocument *pdf_document, gint page, @@ -586,21 +874,22 @@ pdf_document_search_idle_callback (void *data) { PdfDocumentSearch *search = (PdfDocumentSearch*) data; PdfDocument *pdf_document = search->document; - int n_pages, changed_page; + int n_pages; GList *matches; PopplerPage *page; page = poppler_document_get_page (search->document->document, search->search_page); - g_mutex_lock (EV_DOC_MUTEX); + ev_document_doc_mutex_lock (); matches = poppler_page_find_text (page, search->text); - g_mutex_unlock (EV_DOC_MUTEX); + ev_document_doc_mutex_unlock (); search->pages[search->search_page] = matches; - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document)); + ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document), + search->search_page); - changed_page = 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 */ @@ -608,8 +897,6 @@ pdf_document_search_idle_callback (void *data) } if (search->search_page != search->start_page) { - ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document), - changed_page); return TRUE; } @@ -700,7 +987,6 @@ int pdf_document_find_get_n_results (EvDocumentFind *document_find, int page) { PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; - int current_page; if (search) { return g_list_length (search->pages[page]); @@ -719,7 +1005,6 @@ pdf_document_find_get_result (EvDocumentFind *document_find, PdfDocumentSearch *search = pdf_document->search; PopplerPage *poppler_page; PopplerRectangle *r; - int current_page; double height; if (search == NULL) @@ -798,14 +1083,14 @@ pdf_document_find_iface_init (EvDocumentFindIface *iface) } static void -pdf_document_ps_exporter_begin (EvPSExporter *exporter, const char *filename) +pdf_document_ps_exporter_begin (EvPSExporter *exporter, const char *filename, + int first_page, int last_page) { PdfDocument *pdf_document = PDF_DOCUMENT (exporter); - int n_pages; - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (exporter)); - pdf_document->ps_file = poppler_ps_file_new (pdf_document->document, - filename, n_pages); + pdf_document->ps_file = poppler_ps_file_new (pdf_document->document, filename, + first_page, + last_page - first_page + 1); } static void