]> www.fi.muni.cz Git - evince.git/blobdiff - backend/pdf/ev-poppler.cc
Fix selections with poppler-splash.
[evince.git] / backend / pdf / ev-poppler.cc
index 5b0398047c458ec8e84f286739270951c9b20a58..f50407fc091e3f6f76e1ce0b20d399e71de32281 100644 (file)
@@ -45,6 +45,7 @@
 #include "ev-document-transition.h"
 #include "ev-document-forms.h"
 #include "ev-selection.h"
 #include "ev-document-transition.h"
 #include "ev-document-forms.h"
 #include "ev-selection.h"
+#include "ev-transition-effect.h"
 #include "ev-attachment.h"
 #include "ev-image.h"
 
 #include "ev-attachment.h"
 #include "ev-image.h"
 
 #define HAVE_CAIRO_PRINT
 #endif
 
 #define HAVE_CAIRO_PRINT
 #endif
 
+#if POPPLER_MAJOR_VERSION <= 6 || (POPPLER_MAJOR_VERSION == 7 && POPPLER_MINOR_VERSION < 2)
+#define POPPLER_HAS_GDK
+#else
+#ifdef POPPLER_WITH_GDK
+#define POPPLER_HAS_GDK
+#endif
+#endif
+
 typedef struct {
        PdfDocument *document;
        char *text;
 typedef struct {
        PdfDocument *document;
        char *text;
@@ -125,26 +134,26 @@ static void        pdf_print_context_free   (PdfPrintContext   *ctx);
 
 EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document,
                         {
 
 EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document,
                         {
-                                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_FORMS,
-                                                       pdf_document_document_forms_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);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
+                                                                pdf_document_security_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+                                                                pdf_document_document_thumbnails_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
+                                                                pdf_document_document_links_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
+                                                                pdf_document_document_images_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
+                                                                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_FIND,
+                                                                pdf_document_find_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
+                                                                pdf_document_file_exporter_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
+                                                                pdf_selection_iface_init);
+                                EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
+                                                                pdf_document_page_transition_iface_init);
                         });
 
 static void
                         });
 
 static void
@@ -444,27 +453,12 @@ pdf_document_get_attachments (EvDocument *document)
 }
 
 static cairo_surface_t *
 }
 
 static cairo_surface_t *
-pdf_document_render (EvDocument      *document,
-                    EvRenderContext *rc)
+pdf_page_render (PopplerPage     *page,
+                gint             width,
+                gint             height,
+                EvRenderContext *rc)
 {
 {
-       PdfDocument *pdf_document;
        cairo_surface_t *surface;
        cairo_surface_t *surface;
-       double width_points, height_points;
-       gint width, height;
-
-       pdf_document = PDF_DOCUMENT (document);
-
-       set_rc_data (pdf_document, rc);
-
-       poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
-
-       if (rc->rotation == 90 || rc->rotation == 270) {
-               width = (int) ((height_points * rc->scale) + 0.5);
-               height = (int) ((width_points * rc->scale) + 0.5);
-       } else {
-               width = (int) ((width_points * rc->scale) + 0.5);
-               height = (int) ((height_points * rc->scale) + 0.5);
-       }
 
 #ifdef HAVE_POPPLER_PAGE_RENDER
        cairo_t *cr;
 
 #ifdef HAVE_POPPLER_PAGE_RENDER
        cairo_t *cr;
@@ -491,7 +485,7 @@ pdf_document_render (EvDocument      *document,
        }
        cairo_scale (cr, rc->scale, rc->scale);
        cairo_rotate (cr, rc->rotation * G_PI / 180.0);
        }
        cairo_scale (cr, rc->scale, rc->scale);
        cairo_rotate (cr, rc->rotation * G_PI / 180.0);
-       poppler_page_render (POPPLER_PAGE (rc->data), cr);
+       poppler_page_render (page, cr);
        cairo_destroy (cr);
 #else /* HAVE_POPPLER_PAGE_RENDER */
        GdkPixbuf *pixbuf;
        cairo_destroy (cr);
 #else /* HAVE_POPPLER_PAGE_RENDER */
        GdkPixbuf *pixbuf;
@@ -500,7 +494,7 @@ pdf_document_render (EvDocument      *document,
                                 FALSE, 8,
                                 width, height);
 
                                 FALSE, 8,
                                 width, height);
 
-       poppler_page_render_to_pixbuf (POPPLER_PAGE (rc->data),
+       poppler_page_render_to_pixbuf (page,
                                       0, 0,
                                       width, height,
                                       rc->scale,
                                       0, 0,
                                       width, height,
                                       rc->scale,
@@ -510,7 +504,34 @@ pdf_document_render (EvDocument      *document,
        g_object_unref (pixbuf);
 #endif /* HAVE_POPPLER_PAGE_RENDER */
 
        g_object_unref (pixbuf);
 #endif /* HAVE_POPPLER_PAGE_RENDER */
 
-       return surface;
+       return surface; 
+}
+
+static cairo_surface_t *
+pdf_document_render (EvDocument      *document,
+                    EvRenderContext *rc)
+{
+       PdfDocument *pdf_document;
+       double width_points, height_points;
+       gint width, height;
+
+       pdf_document = PDF_DOCUMENT (document);
+
+       set_rc_data (pdf_document, rc);
+
+       poppler_page_get_size (POPPLER_PAGE (rc->data),
+                              &width_points, &height_points);
+       
+       if (rc->rotation == 90 || rc->rotation == 270) {
+               width = (int) ((height_points * rc->scale) + 0.5);
+               height = (int) ((width_points * rc->scale) + 0.5);
+       } else {
+               width = (int) ((width_points * rc->scale) + 0.5);
+               height = (int) ((height_points * rc->scale) + 0.5);
+       }
+       
+       return pdf_page_render (POPPLER_PAGE (rc->data),
+                               width, height, rc);
 }
 
 /* EvDocumentSecurity */
 }
 
 /* EvDocumentSecurity */
@@ -1155,8 +1176,8 @@ pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
 }
 
 static GList *
 }
 
 static GList *
-pdf_document_images_get_images (EvDocumentImages *document_images,
-                               gint              page)
+pdf_document_images_get_image_mapping (EvDocumentImages *document_images,
+                                      gint              page)
 {
        GList *retval = NULL;
        PdfDocument *pdf_document;
 {
        GList *retval = NULL;
        PdfDocument *pdf_document;
@@ -1175,8 +1196,11 @@ pdf_document_images_get_images (EvDocumentImages *document_images,
                image_mapping = (PopplerImageMapping *)list->data;
 
                ev_image_mapping = g_new (EvImageMapping, 1);
                image_mapping = (PopplerImageMapping *)list->data;
 
                ev_image_mapping = g_new (EvImageMapping, 1);
-               
+#ifdef HAVE_POPPLER_PAGE_GET_IMAGE
+               ev_image_mapping->image = ev_image_new (page, image_mapping->image_id);
+#elif POPPLER_HAS_CAIRO
                ev_image_mapping->image = ev_image_new_from_pixbuf (image_mapping->image);
                ev_image_mapping->image = ev_image_new_from_pixbuf (image_mapping->image);
+#endif
                ev_image_mapping->x1 = image_mapping->area.x1;
                ev_image_mapping->x2 = image_mapping->area.x2;
                ev_image_mapping->y1 = image_mapping->area.y1;
                ev_image_mapping->x1 = image_mapping->area.x1;
                ev_image_mapping->x2 = image_mapping->area.x2;
                ev_image_mapping->y1 = image_mapping->area.y1;
@@ -1188,13 +1212,42 @@ pdf_document_images_get_images (EvDocumentImages *document_images,
        poppler_page_free_image_mapping (mapping_list);
        g_object_unref (poppler_page);
 
        poppler_page_free_image_mapping (mapping_list);
        g_object_unref (poppler_page);
 
+       return g_list_reverse (retval);
+}
+
+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;
+       GdkPixbuf       *retval = NULL;
+
+       pdf_document = PDF_DOCUMENT (document_images);
+       poppler_page = poppler_document_get_page (pdf_document->document,
+                                                 ev_image_get_page (image));
+
+       surface = poppler_page_get_image (poppler_page, ev_image_get_id (image));
+       if (surface) {
+               retval = ev_document_misc_pixbuf_from_surface (surface);
+               cairo_surface_destroy (surface);
+       }
+
+       g_object_unref (poppler_page);
+
        return retval;
        return retval;
+#else
+       return GDK_PIXBUF (g_object_ref (ev_image_get_pixbuf (image)));
+#endif /* HAVE_POPPLER_PAGE_GET_IMAGE */
 }
 
 static void
 pdf_document_document_images_iface_init (EvDocumentImagesIface *iface)
 {
 }
 
 static void
 pdf_document_document_images_iface_init (EvDocumentImagesIface *iface)
 {
-       iface->get_images = pdf_document_images_get_images;
+       iface->get_image_mapping = pdf_document_images_get_image_mapping;
+       iface->get_image = pdf_document_images_get_image;
 }
 
 static GdkPixbuf *
 }
 
 static GdkPixbuf *
@@ -1207,7 +1260,7 @@ make_thumbnail_for_page (PdfDocument     *pdf_document,
 
        pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
                                                rc, &width, &height);
 
        pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
                                                rc, &width, &height);
-
+#ifdef POPPLER_HAS_GDK
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
                                 width, height);
        gdk_pixbuf_fill (pixbuf, 0xffffffff);
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
                                 width, height);
        gdk_pixbuf_fill (pixbuf, 0xffffffff);
@@ -1217,6 +1270,16 @@ make_thumbnail_for_page (PdfDocument     *pdf_document,
                                       width, height,
                                       rc->scale, rc->rotation, pixbuf);
        ev_document_fc_mutex_unlock ();
                                       width, height,
                                       rc->scale, rc->rotation, pixbuf);
        ev_document_fc_mutex_unlock ();
+#else
+       cairo_surface_t *surface;
+
+       ev_document_fc_mutex_lock ();
+       surface = pdf_page_render (poppler_page, width, height, rc);
+       ev_document_fc_mutex_unlock ();
+       
+       pixbuf = ev_document_misc_pixbuf_from_surface (surface);
+       cairo_surface_destroy (surface);
+#endif /* POPPLER_HAS_GDK */
 
        return pixbuf;
 }
 
        return pixbuf;
 }
@@ -1228,7 +1291,7 @@ pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails
 {
        PdfDocument *pdf_document;
        PopplerPage *poppler_page;
 {
        PdfDocument *pdf_document;
        PopplerPage *poppler_page;
-       GdkPixbuf *pixbuf;
+       GdkPixbuf *pixbuf = NULL;
        GdkPixbuf *border_pixbuf;
 
        pdf_document = PDF_DOCUMENT (document_thumbnails);
        GdkPixbuf *border_pixbuf;
 
        pdf_document = PDF_DOCUMENT (document_thumbnails);
@@ -1236,7 +1299,22 @@ pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails
        poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
        g_return_val_if_fail (poppler_page != NULL, NULL);
 
        poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
        g_return_val_if_fail (poppler_page != NULL, NULL);
 
+#if POPPLER_MAJOR_VERSION <= 6 || (POPPLER_MAJOR_VERSION == 7 && POPPLER_MINOR_VERSION < 2)
        pixbuf = poppler_page_get_thumbnail (poppler_page);
        pixbuf = poppler_page_get_thumbnail (poppler_page);
+#else
+#ifdef POPPLER_HAS_GDK
+       pixbuf = poppler_page_get_thumbnail_pixbuf (poppler_page);
+#else
+       cairo_surface_t *surface;
+       
+       surface = poppler_page_get_thumbnail (poppler_page);
+       if (surface) {
+               pixbuf = ev_document_misc_pixbuf_from_surface (surface);
+               cairo_surface_destroy (surface);
+       }
+#endif
+#endif
+               
        if (pixbuf) {
                /* Rotate provided thumbnail if needed */
                GdkPixbuf *rotated_pixbuf;
        if (pixbuf) {
                /* Rotate provided thumbnail if needed */
                GdkPixbuf *rotated_pixbuf;
@@ -1822,6 +1900,23 @@ pdf_selection_render_selection (EvSelection      *selection,
 
 #ifdef HAVE_POPPLER_PAGE_RENDER
        cairo_t *cr;
 
 #ifdef HAVE_POPPLER_PAGE_RENDER
        cairo_t *cr;
+       
+#if POPPLER_MAJOR_VERSION <= 6 || (POPPLER_MAJOR_VERSION == 7 && POPPLER_MINOR_VERSION < 2)
+       GdkColor **text_color, **base_color;
+
+       *text_color = text;
+       *base_color = base;
+#else
+       PopplerColor text_color, base_color;
+       
+       text_color.red = text->red;
+       text_color.green = text->green;
+       text_color.blue = text->blue;
+
+       base_color.red = base->red;
+       base_color.green = base->green;
+       base_color.blue = base->blue;
+#endif
 
        if (*surface == NULL) {
                *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
        if (*surface == NULL) {
                *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
@@ -1840,8 +1935,8 @@ pdf_selection_render_selection (EvSelection      *selection,
                                       (PopplerRectangle *)points,
                                       (PopplerRectangle *)old_points,
                                       (PopplerSelectionStyle)style,
                                       (PopplerRectangle *)points,
                                       (PopplerRectangle *)old_points,
                                       (PopplerSelectionStyle)style,
-                                      text,
-                                      base);
+                                      &text_color,
+                                      &base_color);
        cairo_destroy (cr);
 #else /* HAVE_POPPLER_PAGE_RENDER */
        GdkPixbuf *pixbuf;
        cairo_destroy (cr);
 #else /* HAVE_POPPLER_PAGE_RENDER */
        GdkPixbuf *pixbuf;
@@ -1894,6 +1989,32 @@ pdf_selection_get_selected_text (EvSelection     *selection,
        return retval;
 }
 
        return retval;
 }
 
+static GdkRegion *
+create_gdk_region_from_poppler_region (GList *region)
+{
+       GList *l;
+       GdkRegion *retval;
+       
+       retval = gdk_region_new ();
+       
+       for (l = region; l; l = g_list_next (l)) {
+               PopplerRectangle *rectangle;
+               GdkRectangle      rect;
+               
+               rectangle = (PopplerRectangle *)l->data;
+               
+               rect.x = (gint) rectangle->x1;
+               rect.y = (gint) rectangle->y1;
+               rect.width  = (gint) (rectangle->x2 - rectangle->x1);
+               rect.height = (gint) (rectangle->y2 - rectangle->y1);
+               gdk_region_union_with_rect (retval, &rect);
+               
+               poppler_rectangle_free (rectangle);
+       }
+
+       return retval;
+}
+
 static GdkRegion *
 pdf_selection_get_selection_region (EvSelection     *selection,
                                    EvRenderContext *rc,
 static GdkRegion *
 pdf_selection_get_selection_region (EvSelection     *selection,
                                    EvRenderContext *rc,
@@ -1901,16 +2022,28 @@ pdf_selection_get_selection_region (EvSelection     *selection,
                                    EvRectangle     *points)
 {
        PdfDocument *pdf_document;
                                    EvRectangle     *points)
 {
        PdfDocument *pdf_document;
-       GdkRegion *retval;
+       GdkRegion   *retval;
 
        pdf_document = PDF_DOCUMENT (selection);
 
        set_rc_data (pdf_document, rc);
 
        pdf_document = PDF_DOCUMENT (selection);
 
        set_rc_data (pdf_document, rc);
-
-       retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
+       
+#if POPPLER_MAJOR_VERSION <= 6 || (POPPLER_MAJOR_VERSION == 7 && POPPLER_MINOR_VERSION < 2)
+       retval = poppler_page_get_selection_region (POPPLER_PAGE (rc->data),
+                                                   rc->scale,
+                                                   (PopplerSelectionStyle)style,
+                                                   (PopplerRectangle *) points);
+#else
+       GList *region;
+       
+       region = poppler_page_get_selection_region (POPPLER_PAGE (rc->data),
                                                    rc->scale,
                                                    (PopplerSelectionStyle)style,
                                                    (PopplerRectangle *) points);
                                                    rc->scale,
                                                    (PopplerSelectionStyle)style,
                                                    (PopplerRectangle *) points);
+       retval = create_gdk_region_from_poppler_region (region);
+       g_list_free (region);
+#endif
+       
        return retval;
 }
 
        return retval;
 }
 
@@ -1921,6 +2054,7 @@ pdf_selection_get_selection_map (EvSelection     *selection,
        PdfDocument *pdf_document;
        PopplerPage *poppler_page;
        PopplerRectangle points;
        PdfDocument *pdf_document;
        PopplerPage *poppler_page;
        PopplerRectangle points;
+       GList *region;
        GdkRegion *retval;
 
        pdf_document = PDF_DOCUMENT (selection);
        GdkRegion *retval;
 
        pdf_document = PDF_DOCUMENT (selection);
@@ -1930,9 +2064,18 @@ pdf_selection_get_selection_map (EvSelection     *selection,
        points.x1 = 0.0;
        points.y1 = 0.0;
        poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
        points.x1 = 0.0;
        points.y1 = 0.0;
        poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
+       
+#if POPPLER_MAJOR_VERSION <= 6 || (POPPLER_MAJOR_VERSION == 7 && POPPLER_MINOR_VERSION < 2)
        retval = poppler_page_get_selection_region (poppler_page, 1.0,
                                                    POPPLER_SELECTION_GLYPH,
                                                    &points);
        retval = poppler_page_get_selection_region (poppler_page, 1.0,
                                                    POPPLER_SELECTION_GLYPH,
                                                    &points);
+#else
+       region = poppler_page_get_selection_region (poppler_page, 1.0,
+                                                   POPPLER_SELECTION_GLYPH,
+                                                   &points);
+       retval = create_gdk_region_from_poppler_region (region);
+       g_list_free (region);
+#endif
        g_object_unref (poppler_page);
 
        return retval;
        g_object_unref (poppler_page);
 
        return retval;
@@ -1967,10 +2110,49 @@ pdf_document_get_page_duration (EvDocumentTransition *trans,
        return duration;
 }
 
        return duration;
 }
 
+static EvTransitionEffect *
+pdf_document_get_effect (EvDocumentTransition *trans,
+                        gint                  page)
+{
+       PdfDocument            *pdf_document;
+       PopplerPage            *poppler_page;
+       PopplerPageTransition  *page_transition;
+       EvTransitionEffect     *effect;
+
+       pdf_document = PDF_DOCUMENT (trans);
+       poppler_page = poppler_document_get_page (pdf_document->document, page);
+
+       if (!poppler_page)
+               return NULL;
+
+       page_transition = poppler_page_get_transition (poppler_page);
+
+       if (!page_transition) {
+               g_object_unref (poppler_page);
+               return NULL;
+       }
+
+       /* enums in PopplerPageTransition match the EvTransitionEffect ones */
+       effect = ev_transition_effect_new ((EvTransitionEffectType) page_transition->type,
+                                          "alignment", page_transition->alignment,
+                                          "direction", page_transition->direction,
+                                          "duration", page_transition->duration,
+                                          "angle", page_transition->angle,
+                                          "scale", page_transition->scale,
+                                          "rectangular", page_transition->rectangular,
+                                          NULL);
+
+       poppler_page_transition_free (page_transition);
+       g_object_unref (poppler_page);
+
+       return effect;
+}
+
 static void
 pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface)
 {
        iface->get_page_duration = pdf_document_get_page_duration;
 static void
 pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface)
 {
        iface->get_page_duration = pdf_document_get_page_duration;
+       iface->get_effect = pdf_document_get_effect;
 }
 
 /* Forms */
 }
 
 /* Forms */