X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=pdf%2Fev-poppler.cc;h=479a741bb887e4bffb3de39df86f1151d75e3235;hb=f7c3085a0e3c5c813cf9ae40b55fd7390e9373e2;hp=f6b1d64fa195387d2475d5039b84e8d42c3bfd28;hpb=ce1bd095414d0eece573c719202979f498f3ef33;p=evince.git diff --git a/pdf/ev-poppler.cc b/pdf/ev-poppler.cc index f6b1d64f..479a741b 100644 --- a/pdf/ev-poppler.cc +++ b/pdf/ev-poppler.cc @@ -17,22 +17,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "config.h" + #include #include #include #include #include #include +#ifdef HAVE_CAIRO_PDF +#include +#endif #include #include "ev-poppler.h" -#include "ev-ps-exporter.h" +#include "ev-file-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" +#include "ev-document-transition.h" #include "ev-selection.h" #include "ev-attachment.h" @@ -45,6 +51,14 @@ typedef struct { int search_page; } PdfDocumentSearch; +typedef struct { + EvFileExporterFormat format; + PopplerPSFile *ps_file; +#ifdef HAVE_CAIRO_PDF + cairo_t *pdf_cairo; +#endif +} PdfPrintContext; + struct _PdfDocumentClass { GObjectClass parent_class; @@ -55,7 +69,6 @@ struct _PdfDocument GObject parent_instance; PopplerDocument *document; - PopplerPSFile *ps_file; gchar *password; PopplerFontInfo *font_info; @@ -63,6 +76,7 @@ struct _PdfDocument int fonts_scanned_pages; PdfDocumentSearch *search; + PdfPrintContext *print_ctx; }; static void pdf_document_document_iface_init (EvDocumentIface *iface); @@ -71,8 +85,9 @@ static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIfa 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_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, gint page, gint size, @@ -80,9 +95,12 @@ static void pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails gint *height); static int pdf_document_get_n_pages (EvDocument *document); -static EvLinkDest *ev_link_dest_from_dest (PopplerDest *dest); -static EvLink *ev_link_from_action (PopplerAction *action); -static void pdf_document_search_free (PdfDocumentSearch *search); +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); G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, @@ -99,10 +117,12 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, 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); + G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER, + pdf_document_file_exporter_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION, pdf_selection_iface_init); + G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION, + pdf_document_page_transition_iface_init); }); @@ -134,8 +154,10 @@ pdf_document_search_free (PdfDocumentSearch *search) 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->text); + g_free (search); } static void @@ -143,6 +165,11 @@ pdf_document_dispose (GObject *object) { PdfDocument *pdf_document = PDF_DOCUMENT(object); + if (pdf_document->print_ctx) { + 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; @@ -484,8 +511,8 @@ pdf_document_get_info (EvDocument *document) EV_DOCUMENT_INFO_MOD_DATE | EV_DOCUMENT_INFO_LINEARIZED | EV_DOCUMENT_INFO_N_PAGES | - EV_DOCUMENT_INFO_SECURITY; - + EV_DOCUMENT_INFO_SECURITY | + EV_DOCUMENT_INFO_PAPER_SIZE; g_object_get (PDF_DOCUMENT (document)->document, "title", &(info->title), @@ -504,6 +531,14 @@ pdf_document_get_info (EvDocument *document) "linearized", &(info->linearized), NULL); + pdf_document_get_page_size(document, 0, + &(info->paper_width), + &(info->paper_height)); + + // Convert to mm. + info->paper_width = info->paper_width / 72.0f * 25.4f; + info->paper_height = info->paper_height / 72.0f * 25.4f; + switch (layout) { case POPPLER_PAGE_LAYOUT_SINGLE_PAGE: info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE; @@ -781,37 +816,62 @@ pdf_document_links_has_document_links (EvDocumentLinks *document_links) } static EvLinkDest * -ev_link_dest_from_dest (PopplerDest *dest) +ev_link_dest_from_dest (PdfDocument *pdf_document, + PopplerDest *dest) { EvLinkDest *ev_dest = NULL; const char *unimplemented_dest = NULL; g_assert (dest != NULL); - + switch (dest->type) { - case POPPLER_DEST_XYZ: + case POPPLER_DEST_XYZ: { + PopplerPage *poppler_page; + double height; + + poppler_page = poppler_document_get_page (pdf_document->document, + MAX (0, dest->page_num - 1)); + poppler_page_get_size (poppler_page, NULL, &height); ev_dest = ev_link_dest_new_xyz (dest->page_num - 1, dest->left, - dest->top, + height - dest->top, dest->zoom); + g_object_unref (poppler_page); + } break; case POPPLER_DEST_FIT: ev_dest = ev_link_dest_new_fit (dest->page_num - 1); break; - case POPPLER_DEST_FITH: + case POPPLER_DEST_FITH: { + PopplerPage *poppler_page; + double height; + + poppler_page = poppler_document_get_page (pdf_document->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, - dest->top); + height - dest->top); + g_object_unref (poppler_page); + } break; case POPPLER_DEST_FITV: ev_dest = ev_link_dest_new_fitv (dest->page_num - 1, dest->left); break; - case POPPLER_DEST_FITR: + case POPPLER_DEST_FITR: { + PopplerPage *poppler_page; + double height; + + poppler_page = poppler_document_get_page (pdf_document->document, + MAX (0, dest->page_num - 1)); + poppler_page_get_size (poppler_page, NULL, &height); ev_dest = ev_link_dest_new_fitr (dest->page_num - 1, dest->left, - dest->bottom, + height - dest->bottom, dest->right, - dest->top); + height - dest->top); + g_object_unref (poppler_page); + } break; case POPPLER_DEST_FITB: unimplemented_dest = "POPPLER_DEST_FITB"; @@ -829,7 +889,7 @@ ev_link_dest_from_dest (PopplerDest *dest) unimplemented_dest = "POPPLER_DEST_UNKNOWN"; break; } - + if (unimplemented_dest) { g_warning ("Unimplemented named action: %s, please post a " "bug report in Evince bugzilla " @@ -844,7 +904,8 @@ ev_link_dest_from_dest (PopplerDest *dest) } static EvLink * -ev_link_from_action (PopplerAction *action) +ev_link_from_action (PdfDocument *pdf_document, + PopplerAction *action) { EvLink *link = NULL; EvLinkAction *ev_action = NULL; @@ -854,14 +915,14 @@ ev_link_from_action (PopplerAction *action) case POPPLER_ACTION_GOTO_DEST: { EvLinkDest *dest; - dest = ev_link_dest_from_dest (action->goto_dest.dest); + dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest); ev_action = ev_link_action_new_dest (dest); } break; case POPPLER_ACTION_GOTO_REMOTE: { EvLinkDest *dest; - dest = ev_link_dest_from_dest (action->goto_remote.dest); + dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest); ev_action = ev_link_action_new_remote (dest, action->goto_remote.file_name); @@ -926,22 +987,22 @@ build_tree (PdfDocument *pdf_document, dest = poppler_document_find_dest (pdf_document->document, action->goto_dest.dest->named_dest); if (!dest) { - link = ev_link_from_action (action); + link = ev_link_from_action (pdf_document, action); break; } - ev_dest = ev_link_dest_from_dest (dest); + 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 (action); + link = ev_link_from_action (pdf_document, action); } } break; default: - link = ev_link_from_action (action); + link = ev_link_from_action (pdf_document, action); break; } @@ -1017,7 +1078,8 @@ pdf_document_links_get_links (EvDocumentLinks *document_links, link_mapping = (PopplerLinkMapping *)list->data; ev_link_mapping = g_new (EvLinkMapping, 1); - ev_link_mapping->link = ev_link_from_action (link_mapping->action); + ev_link_mapping->link = ev_link_from_action (pdf_document, + link_mapping->action); ev_link_mapping->x1 = link_mapping->area.x1; ev_link_mapping->x2 = link_mapping->area.x2; /* Invert this for X-style coordinates */ @@ -1045,7 +1107,7 @@ pdf_document_links_find_link_dest (EvDocumentLinks *document_links, dest = poppler_document_find_dest (pdf_document->document, link_name); if (dest) { - ev_dest = ev_link_dest_from_dest (dest); + ev_dest = ev_link_dest_from_dest (pdf_document, dest); poppler_dest_free (dest); } @@ -1093,9 +1155,11 @@ make_thumbnail_for_size (PdfDocument *pdf_document, width, height); gdk_pixbuf_fill (pixbuf, 0xffffffff); + ev_document_fc_mutex_lock (); poppler_page_render_to_pixbuf (poppler_page, 0, 0, width, height, scale, rotation, pixbuf); + ev_document_fc_mutex_unlock (); g_object_unref (poppler_page); @@ -1230,10 +1294,6 @@ pdf_document_search_new (PdfDocument *pdf_document, search->text = g_strdup (text); search->pages = g_new0 (GList *, n_pages); - for (i = 0; i < n_pages; i++) { - search->pages[i] = NULL; - } - search->document = pdf_document; /* We add at low priority so the progress bar repaints */ @@ -1273,7 +1333,7 @@ pdf_document_find_begin (EvDocumentFind *document, search_string); } -int +static int pdf_document_find_get_n_results (EvDocumentFind *document_find, int page) { PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; @@ -1285,7 +1345,7 @@ pdf_document_find_get_n_results (EvDocumentFind *document_find, int page) } } -gboolean +static gboolean pdf_document_find_get_result (EvDocumentFind *document_find, int page, int n_result, @@ -1316,7 +1376,7 @@ pdf_document_find_get_result (EvDocumentFind *document_find, return TRUE; } -int +static int pdf_document_find_page_has_results (EvDocumentFind *document_find, int page) { @@ -1325,7 +1385,7 @@ pdf_document_find_page_has_results (EvDocumentFind *document_find, return search && search->pages[page] != NULL; } -double +static double pdf_document_find_get_progress (EvDocumentFind *document_find) { PdfDocumentSearch *search; @@ -1371,52 +1431,135 @@ pdf_document_find_iface_init (EvDocumentFindIface *iface) iface->cancel = pdf_document_find_cancel; } +static const gboolean supported_formats[] = { + TRUE, /* EV_FILE_FORMAT_PS */ +#ifdef HAVE_CAIRO_PDF +#ifdef HAVE_POPPLER_PAGE_RENDER + TRUE, /* EV_FILE_FORMAT_PDF */ +#else + FALSE, /* EV_FILE_FORMAT_PDF */ +#endif +#endif +}; + static void -pdf_document_ps_exporter_begin (EvPSExporter *exporter, const char *filename, - int first_page, int last_page, - double width, double height, gboolean duplex) +pdf_print_context_free (PdfPrintContext *ctx) +{ + if (!ctx) + return; + + if (ctx->ps_file) { + poppler_ps_file_free (ctx->ps_file); + ctx->ps_file = NULL; + } +#ifdef HAVE_CAIRO_PDF + if (ctx->pdf_cairo) { + cairo_destroy (ctx->pdf_cairo); + ctx->pdf_cairo = NULL; + } +#endif + g_free (ctx); +} + +static gboolean +pdf_document_file_exporter_format_supported (EvFileExporter *exporter, + EvFileExporterFormat format) +{ + return supported_formats[format]; +} + +static void +pdf_document_file_exporter_begin (EvFileExporter *exporter, + EvFileExporterFormat format, + const char *filename, + int first_page, + int last_page, + double width, + double height, + gboolean duplex) { PdfDocument *pdf_document = PDF_DOCUMENT (exporter); + PdfPrintContext *ctx; + + if (pdf_document->print_ctx) + pdf_print_context_free (pdf_document->print_ctx); + pdf_document->print_ctx = g_new0 (PdfPrintContext, 1); + ctx = pdf_document->print_ctx; + ctx->format = format; - pdf_document->ps_file = poppler_ps_file_new (pdf_document->document, filename, - first_page, - last_page - first_page + 1); - poppler_ps_file_set_paper_size (pdf_document->ps_file, width, height); - poppler_ps_file_set_duplex (pdf_document->ps_file, duplex); + switch (format) { + case EV_FILE_FORMAT_PS: + ctx->ps_file = poppler_ps_file_new (pdf_document->document, + filename, first_page, + last_page - first_page + 1); + poppler_ps_file_set_paper_size (ctx->ps_file, width, height); + poppler_ps_file_set_duplex (ctx->ps_file, duplex); + + break; + case EV_FILE_FORMAT_PDF: { +#ifdef HAVE_CAIRO_PDF + cairo_surface_t *surface; + + surface = cairo_pdf_surface_create (filename, width, height); + ctx->pdf_cairo = cairo_create (surface); + cairo_surface_destroy (surface); +#endif + } + break; + default: + g_assert_not_reached (); + } } static void -pdf_document_ps_exporter_do_page (EvPSExporter *exporter, EvRenderContext *rc) +pdf_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc) { PdfDocument *pdf_document = PDF_DOCUMENT (exporter); + PdfPrintContext *ctx = pdf_document->print_ctx; PopplerPage *poppler_page; - g_return_if_fail (pdf_document->ps_file != NULL); + g_return_if_fail (pdf_document->print_ctx != NULL); poppler_page = poppler_document_get_page (pdf_document->document, rc->page); - poppler_page_render_to_ps (poppler_page, pdf_document->ps_file); + + switch (ctx->format) { + case EV_FILE_FORMAT_PS: + poppler_page_render_to_ps (poppler_page, ctx->ps_file); + break; + case EV_FILE_FORMAT_PDF: +#ifdef HAVE_POPPLER_PAGE_RENDER + poppler_page_render (poppler_page, ctx->pdf_cairo); +#endif +#ifdef HAVE_CAIRO_PDF + cairo_show_page (ctx->pdf_cairo); +#endif + break; + default: + g_assert_not_reached (); + } + g_object_unref (poppler_page); } static void -pdf_document_ps_exporter_end (EvPSExporter *exporter) +pdf_document_file_exporter_end (EvFileExporter *exporter) { PdfDocument *pdf_document = PDF_DOCUMENT (exporter); - poppler_ps_file_free (pdf_document->ps_file); - pdf_document->ps_file = NULL; + pdf_print_context_free (pdf_document->print_ctx); + pdf_document->print_ctx = NULL; } static void -pdf_document_ps_exporter_iface_init (EvPSExporterIface *iface) +pdf_document_file_exporter_iface_init (EvFileExporterIface *iface) { - iface->begin = pdf_document_ps_exporter_begin; - iface->do_page = pdf_document_ps_exporter_do_page; - iface->end = pdf_document_ps_exporter_end; + iface->format_supported = pdf_document_file_exporter_format_supported; + iface->begin = pdf_document_file_exporter_begin; + iface->do_page = pdf_document_file_exporter_do_page; + iface->end = pdf_document_file_exporter_end; } - -void +static void pdf_selection_render_selection (EvSelection *selection, EvRenderContext *rc, GdkPixbuf **pixbuf, @@ -1451,7 +1594,7 @@ pdf_selection_render_selection (EvSelection *selection, } -GdkRegion * +static GdkRegion * pdf_selection_get_selection_region (EvSelection *selection, EvRenderContext *rc, EvRectangle *points) @@ -1468,7 +1611,7 @@ pdf_selection_get_selection_region (EvSelection *selection, return retval; } -GdkRegion * +static GdkRegion * pdf_selection_get_selection_map (EvSelection *selection, EvRenderContext *rc) { @@ -1498,6 +1641,36 @@ pdf_selection_iface_init (EvSelectionIface *iface) iface->get_selection_map = pdf_selection_get_selection_map; } +/* Page Transitions */ +static gdouble +pdf_document_get_page_duration (EvDocumentTransition *trans, + gint page) +{ +#ifdef HAVE_POPPLER_PAGE_GET_DURATION + PdfDocument *pdf_document; + PopplerPage *poppler_page; + gdouble duration = -1; + + pdf_document = PDF_DOCUMENT (trans); + poppler_page = poppler_document_get_page (pdf_document->document, page); + if (!poppler_page) + return -1; + + duration = poppler_page_get_duration (poppler_page); + g_object_unref (poppler_page); + + return duration; +#else + return -1; +#endif /* HAVE_POPPLER_PAGE_GET_DURATION */ +} + +static void +pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface) +{ + iface->get_page_duration = pdf_document_get_page_duration; +} + PdfDocument * pdf_document_new (void) {