From 85fa11d86616d3a9c5a5cfeba78dd7aa72e7997a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Sun, 29 Jul 2007 14:15:17 +0000 Subject: [PATCH] Allow printing multiple pages per sheet. Fixes bug #395573. 2007-07-29 Carlos Garcia Campos * configure.ac: * backend/pdf/ev-poppler.cc: (pdf_print_context_free), (pdf_document_file_exporter_begin), (pdf_document_file_exporter_do_page), (pdf_document_file_exporter_get_capabilities): * libdocument/ev-file-exporter.h: * shell/ev-jobs.[ch]: (ev_job_print_new), (ev_job_print_run): * shell/ev-window.c: (ev_window_print_send), (ev_window_print_dialog_response_cb): Allow printing multiple pages per sheet. Fixes bug #395573. svn path=/trunk/; revision=2591 --- ChangeLog | 14 +++ backend/pdf/ev-poppler.cc | 151 ++++++++++++++++++++++++++------- configure.ac | 5 ++ libdocument/ev-file-exporter.h | 1 + shell/ev-jobs.c | 6 ++ shell/ev-jobs.h | 2 + shell/ev-window.c | 6 ++ 7 files changed, 153 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 238a1524..1f86db9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-07-29 Carlos Garcia Campos + + * configure.ac: + * backend/pdf/ev-poppler.cc: (pdf_print_context_free), + (pdf_document_file_exporter_begin), + (pdf_document_file_exporter_do_page), + (pdf_document_file_exporter_get_capabilities): + * libdocument/ev-file-exporter.h: + * shell/ev-jobs.[ch]: (ev_job_print_new), (ev_job_print_run): + * shell/ev-window.c: (ev_window_print_send), + (ev_window_print_dialog_response_cb): + + Allow printing multiple pages per sheet. Fixes bug #395573. + 2007-07-29 Nickolay V. Shmyrev * shell/ev-view.c: (tip_from_link): diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index 4b6b114e..38a96a53 100644 --- a/backend/pdf/ev-poppler.cc +++ b/backend/pdf/ev-poppler.cc @@ -32,6 +32,9 @@ #ifdef HAVE_CAIRO_PDF #include #endif +#ifdef HAVE_CAIRO_PS +#include +#endif #include #include "ev-poppler.h" @@ -49,6 +52,10 @@ #include "ev-attachment.h" #include "ev-image.h" +#if defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS) +#define HAVE_CAIRO_PRINT +#endif + typedef struct { PdfDocument *document; char *text; @@ -61,8 +68,17 @@ typedef struct { typedef struct { EvFileExporterFormat format; PopplerPSFile *ps_file; -#ifdef HAVE_CAIRO_PDF - cairo_t *pdf_cairo; + + /* Pages per sheet */ + gint pages_per_sheet; + gint pages_printed; + gint pages_x; + gint pages_y; + gdouble page_width; + gdouble page_height; + +#ifdef HAVE_CAIRO_PRINT + cairo_t *cr; #endif } PdfPrintContext; @@ -1516,10 +1532,10 @@ pdf_print_context_free (PdfPrintContext *ctx) 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; +#ifdef HAVE_CAIRO_PRINT + if (ctx->cr) { + cairo_destroy (ctx->cr); + ctx->cr = NULL; } #endif g_free (ctx); @@ -1531,35 +1547,87 @@ pdf_document_file_exporter_begin (EvFileExporter *exporter, { PdfDocument *pdf_document = PDF_DOCUMENT (exporter); PdfPrintContext *ctx; - + gdouble width, height; + gboolean change_orient = FALSE; +#ifdef HAVE_CAIRO_PRINT + cairo_surface_t *surface = NULL; +#endif + 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 = fc->format; - + ctx->pages_per_sheet = fc->pages_per_sheet; + + switch (fc->pages_per_sheet) { + default: + case 1: + ctx->pages_x = 1; + ctx->pages_y = 1; + break; + case 2: + change_orient = TRUE; + ctx->pages_x = 2; + ctx->pages_y = 1; + break; + case 4: + ctx->pages_x = 2; + ctx->pages_y = 2; + break; + case 6: + change_orient = TRUE; + ctx->pages_x = 3; + ctx->pages_y = 2; + break; + case 9: + ctx->pages_x = 3; + ctx->pages_y = 3; + break; + case 16: + ctx->pages_x = 4; + ctx->pages_y = 4; + break; + } + + if (change_orient) { + width = fc->paper_height; + height = fc->paper_width; + } else { + width = fc->paper_width; + height = fc->paper_height; + } + + ctx->page_width = width / ctx->pages_x; + ctx->page_height = height / ctx->pages_y; + + ctx->pages_printed = 0; + switch (fc->format) { case EV_FILE_FORMAT_PS: +#ifdef HAVE_CAIRO_PS + surface = cairo_ps_surface_create (fc->filename, width, height); +#else ctx->ps_file = poppler_ps_file_new (pdf_document->document, fc->filename, fc->first_page, fc->last_page - fc->first_page + 1); poppler_ps_file_set_paper_size (ctx->ps_file, fc->paper_width, fc->paper_height); poppler_ps_file_set_duplex (ctx->ps_file, fc->duplex); - +#endif /* HAVE_CAIRO_PS */ break; - case EV_FILE_FORMAT_PDF: { + case EV_FILE_FORMAT_PDF: #ifdef HAVE_CAIRO_PDF - cairo_surface_t *surface; - - surface = cairo_pdf_surface_create (fc->filename, fc->paper_width, fc->paper_height); - ctx->pdf_cairo = cairo_create (surface); - cairo_surface_destroy (surface); + surface = cairo_pdf_surface_create (fc->filename, width, height); #endif - } break; default: g_assert_not_reached (); } + +#ifdef HAVE_CAIRO_PRINT + ctx->cr = cairo_create (surface); + cairo_surface_destroy (surface); +#endif } static void @@ -1569,30 +1637,41 @@ pdf_document_file_exporter_do_page (EvFileExporter *exporter, PdfDocument *pdf_document = PDF_DOCUMENT (exporter); PdfPrintContext *ctx = pdf_document->print_ctx; PopplerPage *poppler_page; +#ifdef HAVE_CAIRO_PRINT + gdouble page_width, page_height; + gint x, y; +#endif g_return_if_fail (pdf_document->print_ctx != NULL); poppler_page = poppler_document_get_page (pdf_document->document, rc->page); + +#ifdef HAVE_CAIRO_PRINT + x = (ctx->pages_printed % ctx->pages_per_sheet) % ctx->pages_x; + y = (ctx->pages_printed % ctx->pages_per_sheet) / ctx->pages_x; + poppler_page_get_size (poppler_page, &page_width, &page_height); + + cairo_save (ctx->cr); + cairo_translate (ctx->cr, + x * ctx->page_width, + y * ctx->page_height); + cairo_scale (ctx->cr, + ctx->page_width / page_width, + ctx->page_height / page_height); - 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_CAIRO_PDF - cairo_save (ctx->pdf_cairo); -#endif #ifdef HAVE_POPPLER_PAGE_RENDER - poppler_page_render (poppler_page, ctx->pdf_cairo); -#endif -#ifdef HAVE_CAIRO_PDF - cairo_show_page (ctx->pdf_cairo); - cairo_restore (ctx->pdf_cairo); + poppler_page_render (poppler_page, ctx->cr); #endif - break; - default: - g_assert_not_reached (); + ctx->pages_printed++; + + if (ctx->pages_printed % ctx->pages_per_sheet == 0) { + cairo_show_page (ctx->cr); } + cairo_restore (ctx->cr); +#else /* HAVE_CAIRO_PRINT */ + if (ctx->format == EV_FILE_FORMAT_PS) + poppler_page_render_to_ps (poppler_page, ctx->ps_file); +#endif /* HAVE_CAIRO_PRINT */ g_object_unref (poppler_page); } @@ -1615,6 +1694,14 @@ pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter) EV_FILE_EXPORTER_CAN_COLLATE | EV_FILE_EXPORTER_CAN_REVERSE | 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 EV_FILE_EXPORTER_CAN_GENERATE_PDF | diff --git a/configure.ac b/configure.ac index d6967870..5b65fd7a 100644 --- a/configure.ac +++ b/configure.ac @@ -257,6 +257,11 @@ if test "x$enable_pdf" = "xyes"; then if test x$enable_cairo_pdf == xyes; then AC_DEFINE([HAVE_CAIRO_PDF], [1], [defined if cairo-pdf is available]) fi + + PKG_CHECK_MODULES(CAIRO_PS, cairo-ps, enable_cairo_ps=yes, enable_cairo_ps=no) + if test x$enable_cairo_ps == xyes; then + AC_DEFINE([HAVE_CAIRO_PS], [1], [defined if cairo-ps is available]) + fi else AC_MSG_WARN("PDF support is disabled since poppler-glib library version $POPPLER_REQUIRED or newer not found") fi diff --git a/libdocument/ev-file-exporter.h b/libdocument/ev-file-exporter.h index 7fadb1ae..c05ea27d 100644 --- a/libdocument/ev-file-exporter.h +++ b/libdocument/ev-file-exporter.h @@ -55,6 +55,7 @@ typedef struct { gdouble paper_width; gdouble paper_height; gboolean duplex; + gint pages_per_sheet; } EvFileExporterContext; #define EV_TYPE_FILE_EXPORTER (ev_file_exporter_get_type ()) diff --git a/shell/ev-jobs.c b/shell/ev-jobs.c index d5d45f22..8e140f88 100644 --- a/shell/ev-jobs.c +++ b/shell/ev-jobs.c @@ -326,6 +326,8 @@ render_finished_cb (EvDocument *document, /* FIXME: ps backend should be ported to cairo */ job->surface = ev_document_misc_surface_from_pixbuf (pixbuf); + job->page_ready = TRUE; + g_signal_emit (job, job_render_signals[PAGE_READY], 0); EV_JOB (job)->finished = TRUE; ev_job_finished (EV_JOB (job)); } @@ -562,6 +564,7 @@ ev_job_print_new (EvDocument *document, EvPrintRange *ranges, gint n_ranges, EvPrintPageSet page_set, + gint pages_per_sheet, gint copies, gdouble collate, gdouble reverse) @@ -584,6 +587,8 @@ ev_job_print_new (EvDocument *document, job->n_ranges = n_ranges; job->page_set = page_set; + + job->pages_per_sheet = pages_per_sheet; job->copies = copies; job->collate = collate; @@ -711,6 +716,7 @@ ev_job_print_run (EvJobPrint *job) fc.paper_width = job->width; fc.paper_height = job->height; fc.duplex = FALSE; + fc.pages_per_sheet = job->pages_per_sheet; ev_document_doc_mutex_lock (); ev_file_exporter_begin (EV_FILE_EXPORTER (document), &fc); diff --git a/shell/ev-jobs.h b/shell/ev-jobs.h index c0a4036f..1f348d81 100644 --- a/shell/ev-jobs.h +++ b/shell/ev-jobs.h @@ -199,6 +199,7 @@ struct _EvJobPrint gint n_ranges; EvPrintPageSet page_set; gint copies; + gint pages_per_sheet; gboolean collate; gboolean reverse; gdouble width; @@ -264,6 +265,7 @@ EvJob *ev_job_print_new (EvDocument *document, EvPrintRange *ranges, gint n_ranges, EvPrintPageSet page_set, + gint pages_per_sheet, gint copies, gdouble collate, gdouble reverse); diff --git a/shell/ev-window.c b/shell/ev-window.c index 7f928a5f..233067b3 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -2220,6 +2220,8 @@ ev_window_print_send (EvWindow *window, gtk_print_settings_set_collate (settings, FALSE); if (capabilities & EV_FILE_EXPORTER_CAN_REVERSE) gtk_print_settings_set_reverse (settings, FALSE); + if (capabilities & EV_FILE_EXPORTER_CAN_NUMBER_UP) + gtk_print_settings_set_number_up (settings, 1); if (window->priv->print_preview) { gchar *uri; @@ -2294,6 +2296,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog, EvPrintPageSet page_set; gint n_ranges = 0; gint copies; + gint pages_per_sheet; gboolean collate; gboolean reverse; gdouble scale; @@ -2385,6 +2388,8 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog, height *= scale; } + pages_per_sheet = gtk_print_settings_get_number_up (window->priv->print_settings); + copies = gtk_print_settings_get_n_copies (window->priv->print_settings); collate = gtk_print_settings_get_collate (window->priv->print_settings); reverse = gtk_print_settings_get_reverse (window->priv->print_settings); @@ -2394,6 +2399,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog, width, height, ranges, n_ranges, page_set, + pages_per_sheet, copies, collate, reverse); -- 2.43.5