478 lines
15 KiB
Diff
478 lines
15 KiB
Diff
From 69f69eed816b89be9a01a48a1f0643d1fd496118 Mon Sep 17 00:00:00 2001
|
|
From: Nils Philippsen <nils@redhat.com>
|
|
Date: Fri, 6 May 2011 11:58:44 +0200
|
|
Subject: [PATCH] patch: poppler-0.17
|
|
|
|
Squashed commit of the following:
|
|
|
|
commit 529d940222dfc352d41fbf72de29134421aa4002
|
|
Author: Nils Philippsen <nils@redhat.com>
|
|
Date: Fri May 6 11:50:30 2011 +0200
|
|
|
|
use code based on pixbufs instead of cairo surfaces
|
|
|
|
this is done to avoid adding to libgimp, thanks to Mukund Sivaraman for
|
|
hints how to do this
|
|
|
|
commit f8671d8767d4cdab830dc06310e96c63a88ec0fd
|
|
Author: Mukund Sivaraman <muks@banu.com>
|
|
Date: Thu Apr 21 13:57:13 2011 +0530
|
|
|
|
file-pdf-load: Update attribution, removing bogus copyright
|
|
(cherry picked from commit e999122e0b20b6ccd6bde3ce039bb64068fc0019)
|
|
|
|
commit 89a78f2590d298dac2f42e6d9a3016fc5d672c70
|
|
Author: Nils Philippsen <nils@redhat.com>
|
|
Date: Thu Apr 21 13:52:18 2011 +0200
|
|
|
|
file-pdf-load: Use better API + cleanups
|
|
|
|
* fixes issues with poppler 0.17 completely
|
|
* uses new libgimp API to pass surfaces instead of pixbufs
|
|
* uses GTK+ 3 API to convert surfaces to pixbufs where available
|
|
(backported from commit 7bdadd80ba479d6ff904e276d805e16f6b940ee2)
|
|
|
|
commit 4e92302c4a14a961f112587a0ad86696c88da2f8
|
|
Author: Nils Philippsen <nils@redhat.com>
|
|
Date: Thu Apr 21 13:38:08 2011 +0200
|
|
|
|
file-pdf-load: Don't use deprecated API (bug #646947)
|
|
|
|
(cherry picked from commit 9b3e1c91fd2eac69da6947ec9c7fbf10096ba237)
|
|
|
|
Conflicts:
|
|
|
|
plug-ins/common/file-pdf.c
|
|
---
|
|
plug-ins/common/file-pdf.c | 323 ++++++++++++++++++++++++++++++++++++++------
|
|
1 files changed, 283 insertions(+), 40 deletions(-)
|
|
|
|
diff --git a/plug-ins/common/file-pdf.c b/plug-ins/common/file-pdf.c
|
|
index a43b459..43c2b7d 100644
|
|
--- a/plug-ins/common/file-pdf.c
|
|
+++ b/plug-ins/common/file-pdf.c
|
|
@@ -4,6 +4,9 @@
|
|
*
|
|
* Copyright (C) 2005 Nathan Summers
|
|
*
|
|
+ * Some code in render_page_to_surface() borrowed from
|
|
+ * poppler.git/glib/poppler-page.cc.
|
|
+ *
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
@@ -80,16 +83,20 @@ static gboolean load_dialog (PopplerDocument *doc,
|
|
static PopplerDocument * open_document (const gchar *filename,
|
|
GError **error);
|
|
|
|
-static GdkPixbuf * get_thumbnail (PopplerDocument *doc,
|
|
+static cairo_surface_t * get_thumb_surface (PopplerDocument *doc,
|
|
+ gint page,
|
|
+ gint preferred_size);
|
|
+
|
|
+static GdkPixbuf * get_thumb_pixbuf (PopplerDocument *doc,
|
|
gint page,
|
|
gint preferred_size);
|
|
|
|
static gint32 layer_from_pixbuf (gint32 image,
|
|
- const gchar *layer_name,
|
|
- gint position,
|
|
- GdkPixbuf *buf,
|
|
- gdouble progress_start,
|
|
- gdouble progress_scale);
|
|
+ const gchar *layer_name,
|
|
+ gint position,
|
|
+ GdkPixbuf *pixbuf,
|
|
+ gdouble progress_start,
|
|
+ gdouble progress_scale);
|
|
|
|
/**
|
|
** the following was formerly part of
|
|
@@ -433,11 +440,12 @@ run (const gchar *name,
|
|
}
|
|
else
|
|
{
|
|
- gdouble width = 0;
|
|
- gdouble height = 0;
|
|
- gdouble scale;
|
|
- gint32 image = -1;
|
|
- GdkPixbuf *pixbuf = NULL;
|
|
+ gdouble width = 0;
|
|
+ gdouble height = 0;
|
|
+ gdouble scale;
|
|
+ gint32 image = -1;
|
|
+ gint num_pages = 0;
|
|
+ GdkPixbuf *pixbuf = NULL;
|
|
|
|
/* Possibly retrieve last settings */
|
|
gimp_get_data (LOAD_PROC, &loadvals);
|
|
@@ -455,7 +463,10 @@ run (const gchar *name,
|
|
g_object_unref (page);
|
|
}
|
|
|
|
- pixbuf = get_thumbnail (doc, 0, param[1].data.d_int32);
|
|
+ num_pages = poppler_document_get_n_pages (doc);
|
|
+
|
|
+ pixbuf = get_thumb_pixbuf (doc, 0, param[1].data.d_int32);
|
|
+
|
|
g_object_unref (doc);
|
|
}
|
|
|
|
@@ -548,6 +559,187 @@ open_document (const gchar *filename,
|
|
return doc;
|
|
}
|
|
|
|
+/* FIXME: Remove this someday when we depend fully on GTK+ >= 3 */
|
|
+
|
|
+#if (!GTK_CHECK_VERSION (3, 0, 0))
|
|
+
|
|
+static cairo_format_t
|
|
+gdk_cairo_format_for_content (cairo_content_t content)
|
|
+{
|
|
+ switch (content)
|
|
+ {
|
|
+ case CAIRO_CONTENT_COLOR:
|
|
+ return CAIRO_FORMAT_RGB24;
|
|
+ case CAIRO_CONTENT_ALPHA:
|
|
+ return CAIRO_FORMAT_A8;
|
|
+ case CAIRO_CONTENT_COLOR_ALPHA:
|
|
+ default:
|
|
+ return CAIRO_FORMAT_ARGB32;
|
|
+ }
|
|
+}
|
|
+
|
|
+static cairo_surface_t *
|
|
+gdk_cairo_surface_coerce_to_image (cairo_surface_t *surface,
|
|
+ cairo_content_t content,
|
|
+ int src_x,
|
|
+ int src_y,
|
|
+ int width,
|
|
+ int height)
|
|
+{
|
|
+ cairo_surface_t *copy;
|
|
+ cairo_t *cr;
|
|
+
|
|
+ copy = cairo_image_surface_create (gdk_cairo_format_for_content (content),
|
|
+ width,
|
|
+ height);
|
|
+
|
|
+ cr = cairo_create (copy);
|
|
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
|
+ cairo_set_source_surface (cr, surface, -src_x, -src_y);
|
|
+ cairo_paint (cr);
|
|
+ cairo_destroy (cr);
|
|
+
|
|
+ return copy;
|
|
+}
|
|
+
|
|
+static void
|
|
+convert_alpha (guchar *dest_data,
|
|
+ int dest_stride,
|
|
+ guchar *src_data,
|
|
+ int src_stride,
|
|
+ int src_x,
|
|
+ int src_y,
|
|
+ int width,
|
|
+ int height)
|
|
+{
|
|
+ int x, y;
|
|
+
|
|
+ src_data += src_stride * src_y + src_x * 4;
|
|
+
|
|
+ for (y = 0; y < height; y++) {
|
|
+ guint32 *src = (guint32 *) src_data;
|
|
+
|
|
+ for (x = 0; x < width; x++) {
|
|
+ guint alpha = src[x] >> 24;
|
|
+
|
|
+ if (alpha == 0)
|
|
+ {
|
|
+ dest_data[x * 4 + 0] = 0;
|
|
+ dest_data[x * 4 + 1] = 0;
|
|
+ dest_data[x * 4 + 2] = 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
|
|
+ dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
|
|
+ dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
|
|
+ }
|
|
+ dest_data[x * 4 + 3] = alpha;
|
|
+ }
|
|
+
|
|
+ src_data += src_stride;
|
|
+ dest_data += dest_stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+convert_no_alpha (guchar *dest_data,
|
|
+ int dest_stride,
|
|
+ guchar *src_data,
|
|
+ int src_stride,
|
|
+ int src_x,
|
|
+ int src_y,
|
|
+ int width,
|
|
+ int height)
|
|
+{
|
|
+ int x, y;
|
|
+
|
|
+ src_data += src_stride * src_y + src_x * 4;
|
|
+
|
|
+ for (y = 0; y < height; y++) {
|
|
+ guint32 *src = (guint32 *) src_data;
|
|
+
|
|
+ for (x = 0; x < width; x++) {
|
|
+ dest_data[x * 3 + 0] = src[x] >> 16;
|
|
+ dest_data[x * 3 + 1] = src[x] >> 8;
|
|
+ dest_data[x * 3 + 2] = src[x];
|
|
+ }
|
|
+
|
|
+ src_data += src_stride;
|
|
+ dest_data += dest_stride;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * gdk_pixbuf_get_from_surface:
|
|
+ * @surface: surface to copy from
|
|
+ * @src_x: Source X coordinate within @surface
|
|
+ * @src_y: Source Y coordinate within @surface
|
|
+ * @width: Width in pixels of region to get
|
|
+ * @height: Height in pixels of region to get
|
|
+ *
|
|
+ * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
|
|
+ * representation inside a #GdkPixbuf. This allows you to efficiently read
|
|
+ * individual pixels from cairo surfaces. For #GdkWindows, use
|
|
+ * gdk_pixbuf_get_from_window() instead.
|
|
+ *
|
|
+ * This function will create an RGB pixbuf with 8 bits per channel.
|
|
+ * The pixbuf will contain an alpha channel if the @surface contains one.
|
|
+ *
|
|
+ * Return value: (transfer full): A newly-created pixbuf with a reference
|
|
+ * count of 1, or %NULL on error
|
|
+ */
|
|
+static GdkPixbuf *
|
|
+gdk_pixbuf_get_from_surface (cairo_surface_t *surface,
|
|
+ gint src_x,
|
|
+ gint src_y,
|
|
+ gint width,
|
|
+ gint height)
|
|
+{
|
|
+ cairo_content_t content;
|
|
+ GdkPixbuf *dest;
|
|
+
|
|
+ /* General sanity checks */
|
|
+ g_return_val_if_fail (surface != NULL, NULL);
|
|
+ g_return_val_if_fail (width > 0 && height > 0, NULL);
|
|
+
|
|
+ content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
|
|
+ dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
|
+ !!(content & CAIRO_CONTENT_ALPHA),
|
|
+ 8,
|
|
+ width, height);
|
|
+
|
|
+ surface = gdk_cairo_surface_coerce_to_image (surface, content,
|
|
+ src_x, src_y,
|
|
+ width, height);
|
|
+ cairo_surface_flush (surface);
|
|
+ if (cairo_surface_status (surface) || dest == NULL)
|
|
+ {
|
|
+ cairo_surface_destroy (surface);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (gdk_pixbuf_get_has_alpha (dest))
|
|
+ convert_alpha (gdk_pixbuf_get_pixels (dest),
|
|
+ gdk_pixbuf_get_rowstride (dest),
|
|
+ cairo_image_surface_get_data (surface),
|
|
+ cairo_image_surface_get_stride (surface),
|
|
+ 0, 0,
|
|
+ width, height);
|
|
+ else
|
|
+ convert_no_alpha (gdk_pixbuf_get_pixels (dest),
|
|
+ gdk_pixbuf_get_rowstride (dest),
|
|
+ cairo_image_surface_get_data (surface),
|
|
+ cairo_image_surface_get_stride (surface),
|
|
+ 0, 0,
|
|
+ width, height);
|
|
+
|
|
+ cairo_surface_destroy (surface);
|
|
+ return dest;
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
static gint32
|
|
layer_from_pixbuf (gint32 image,
|
|
const gchar *layer_name,
|
|
@@ -566,6 +758,54 @@ layer_from_pixbuf (gint32 image,
|
|
return layer;
|
|
}
|
|
|
|
+static cairo_surface_t *
|
|
+render_page_to_surface (PopplerPage *page,
|
|
+ int width,
|
|
+ int height,
|
|
+ double scale)
|
|
+{
|
|
+ cairo_surface_t *surface;
|
|
+ cairo_t *cr;
|
|
+
|
|
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
|
+ cr = cairo_create (surface);
|
|
+
|
|
+ cairo_save (cr);
|
|
+ cairo_translate (cr, 0.0, 0.0);
|
|
+
|
|
+ if (scale != 1.0)
|
|
+ cairo_scale (cr, scale, scale);
|
|
+
|
|
+ poppler_page_render (page, cr);
|
|
+ cairo_restore (cr);
|
|
+
|
|
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
|
|
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
|
+ cairo_paint (cr);
|
|
+
|
|
+ cairo_destroy (cr);
|
|
+
|
|
+ return surface;
|
|
+}
|
|
+
|
|
+static GdkPixbuf *
|
|
+render_page_to_pixbuf (PopplerPage *page,
|
|
+ int width,
|
|
+ int height,
|
|
+ double scale)
|
|
+{
|
|
+ GdkPixbuf *pixbuf;
|
|
+ cairo_surface_t *surface;
|
|
+
|
|
+ surface = render_page_to_surface (page, width, height, scale);
|
|
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
|
|
+ cairo_image_surface_get_width (surface),
|
|
+ cairo_image_surface_get_height (surface));
|
|
+ cairo_surface_destroy (surface);
|
|
+
|
|
+ return pixbuf;
|
|
+}
|
|
+
|
|
static gint32
|
|
load_image (PopplerDocument *doc,
|
|
const gchar *filename,
|
|
@@ -597,7 +837,7 @@ load_image (PopplerDocument *doc,
|
|
gdouble page_width;
|
|
gdouble page_height;
|
|
|
|
- GdkPixbuf *buf;
|
|
+ GdkPixbuf *pixbuf;
|
|
gint width;
|
|
gint height;
|
|
|
|
@@ -627,15 +867,13 @@ load_image (PopplerDocument *doc,
|
|
gimp_image_set_resolution (image_ID, resolution, resolution);
|
|
}
|
|
|
|
- buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
|
|
-
|
|
- poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf);
|
|
+ pixbuf = render_page_to_pixbuf (page, width, height, scale);
|
|
|
|
- layer_from_pixbuf (image_ID, page_label, i, buf,
|
|
+ layer_from_pixbuf (image_ID, page_label, i, pixbuf,
|
|
doc_progress, 1.0 / pages->n_pages);
|
|
|
|
g_free (page_label);
|
|
- g_object_unref (buf);
|
|
+ g_object_unref(pixbuf);
|
|
|
|
doc_progress = (double) (i + 1) / pages->n_pages;
|
|
gimp_progress_update (doc_progress);
|
|
@@ -676,30 +914,22 @@ load_image (PopplerDocument *doc,
|
|
return image_ID;
|
|
}
|
|
|
|
-static GdkPixbuf *
|
|
-get_thumbnail (PopplerDocument *doc,
|
|
- gint page_num,
|
|
- gint preferred_size)
|
|
+static cairo_surface_t *
|
|
+get_thumb_surface (PopplerDocument *doc,
|
|
+ gint page_num,
|
|
+ gint preferred_size)
|
|
{
|
|
PopplerPage *page;
|
|
- GdkPixbuf *pixbuf;
|
|
+ cairo_surface_t *surface;
|
|
|
|
page = poppler_document_get_page (doc, page_num);
|
|
|
|
if (! page)
|
|
return NULL;
|
|
|
|
- /* XXX: Remove conditional when we depend on poppler 0.8.0, but also
|
|
- * add configure check to make sure POPPLER_WITH_GDK is enabled!
|
|
- */
|
|
-#ifdef POPPLER_WITH_GDK
|
|
- pixbuf = poppler_page_get_thumbnail_pixbuf (page);
|
|
-#else
|
|
- pixbuf = poppler_page_get_thumbnail (page);
|
|
-#endif
|
|
-
|
|
+ surface = poppler_page_get_thumbnail (page);
|
|
|
|
- if (! pixbuf)
|
|
+ if (! surface)
|
|
{
|
|
gdouble width;
|
|
gdouble height;
|
|
@@ -712,15 +942,28 @@ get_thumbnail (PopplerDocument *doc,
|
|
width *= scale;
|
|
height *= scale;
|
|
|
|
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
|
|
- width, height);
|
|
-
|
|
- poppler_page_render_to_pixbuf (page,
|
|
- 0, 0, width, height, scale, 0, pixbuf);
|
|
+ surface = render_page_to_surface (page, width, height, scale);
|
|
}
|
|
|
|
g_object_unref (page);
|
|
|
|
+ return surface;
|
|
+}
|
|
+
|
|
+static GdkPixbuf *
|
|
+get_thumb_pixbuf (PopplerDocument *doc,
|
|
+ gint page_num,
|
|
+ gint preferred_size)
|
|
+{
|
|
+ cairo_surface_t *surface;
|
|
+ GdkPixbuf *pixbuf;
|
|
+
|
|
+ surface = get_thumb_surface (doc, page_num, preferred_size);
|
|
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
|
|
+ cairo_image_surface_get_width (surface),
|
|
+ cairo_image_surface_get_height (surface));
|
|
+ cairo_surface_destroy (surface);
|
|
+
|
|
return pixbuf;
|
|
}
|
|
|
|
@@ -769,8 +1012,8 @@ thumbnail_thread (gpointer data)
|
|
idle_data->page_no = i;
|
|
|
|
/* FIXME get preferred size from somewhere? */
|
|
- idle_data->pixbuf = get_thumbnail (thread_data->document, i,
|
|
- THUMBNAIL_SIZE);
|
|
+ idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i,
|
|
+ THUMBNAIL_SIZE);
|
|
|
|
g_idle_add (idle_set_thumbnail, idle_data);
|
|
|
|
--
|
|
1.7.5
|
|
|