]> www.fi.muni.cz Git - evince.git/blobdiff - backend/pdf/ev-poppler.cc
Updated Occitan translation
[evince.git] / backend / pdf / ev-poppler.cc
index 1c9f4ea3a94c7ee73a216e6afb4a1dbcecc2f991..38a01fd49679f8fe81d2383a82347fb38133dbd7 100644 (file)
@@ -32,6 +32,9 @@
 #ifdef HAVE_CAIRO_PDF
 #include <cairo-pdf.h>
 #endif
+#ifdef HAVE_CAIRO_PS
+#include <cairo-ps.h>
+#endif
 #include <glib/gi18n.h>
 
 #include "ev-poppler.h"
 #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;
 
@@ -110,6 +126,7 @@ static EvLink     *ev_link_from_action      (PdfDocument       *pdf_document,
 static void        pdf_document_search_free (PdfDocumentSearch *search);
 static void        pdf_print_context_free   (PdfPrintContext   *ctx);
 
+#ifdef HAVE_FORMS
 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                          {
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
@@ -122,10 +139,8 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                                                        pdf_document_document_links_iface_init);
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
                                                        pdf_document_document_images_iface_init);
-#ifdef HAVE_FORMS
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
                                                        pdf_document_document_forms_iface_init);
-#endif /* HAVE_FORMS */
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
                                                        pdf_document_document_fonts_iface_init);
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
@@ -137,7 +152,31 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
                                                        pdf_document_page_transition_iface_init);
                         });
-
+#else /* !HAVE_FORMS */
+G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
+                         {
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
+                                                       pdf_document_document_iface_init);
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
+                                                       pdf_document_security_iface_init);
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+                                                       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_IMAGES,
+                                                       pdf_document_document_images_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_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);
+                        });
+#endif /* HAVE_FORMS */
 
 static void
 set_rc_data (PdfDocument     *pdf_document,
@@ -1254,7 +1293,15 @@ pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails
        g_return_val_if_fail (poppler_page != NULL, NULL);
 
        pixbuf = poppler_page_get_thumbnail (poppler_page);
-       if (!pixbuf) {
+       if (pixbuf) {
+               /* Rotate provided thumbnail if needed */
+               GdkPixbuf *rotated_pixbuf;
+
+               rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
+                                                          (GdkPixbufRotation) (360 - rc->rotation));
+               g_object_unref (pixbuf);
+               pixbuf = rotated_pixbuf;
+       } else {
                /* There is no provided thumbnail.  We need to make one. */
                pixbuf = make_thumbnail_for_page (pdf_document, poppler_page, rc);
        }
@@ -1506,17 +1553,6 @@ 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_print_context_free (PdfPrintContext *ctx)
 {
@@ -1527,95 +1563,146 @@ 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);
 }
 
-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)
+pdf_document_file_exporter_begin (EvFileExporter        *exporter,
+                                 EvFileExporterContext *fc)
 {
        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 = format;
-       
-       switch (format) {
+       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,
-                                                           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);
-
+                                                           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 (filename, width, 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
-pdf_document_file_exporter_do_page (EvFileExporter *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;
+#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);
 }
@@ -1629,13 +1716,38 @@ pdf_document_file_exporter_end (EvFileExporter *exporter)
        pdf_document->print_ctx = NULL;
 }
 
+static EvFileExporterCapabilities
+pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
+{
+       return  (EvFileExporterCapabilities) (
+               EV_FILE_EXPORTER_CAN_PAGE_SET |
+               EV_FILE_EXPORTER_CAN_COPIES |
+               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 |
+#endif
+#endif
+               EV_FILE_EXPORTER_CAN_GENERATE_PS);
+}
+
 static void
 pdf_document_file_exporter_iface_init (EvFileExporterIface *iface)
 {
-       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;
+       iface->get_capabilities = pdf_document_file_exporter_get_capabilities;
 }
 
 static void
@@ -1841,7 +1953,10 @@ ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
                        field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
                        field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
                        field_text->is_password = poppler_form_field_text_is_password (poppler_field);
-
+                       
+#ifdef HAVE_POPPLER_FORM_FIELD_TEXT_GET_MAX_LEN
+                       field_text->max_len = poppler_form_field_text_get_max_len (poppler_field);
+#endif
                        field_text->text = poppler_form_field_text_get_text (poppler_field);
 
                }