From a915dce96f6d7d75ae09ec5355a404f00fc0460e Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Tue, 3 May 2011 15:58:39 +0200 Subject: [PATCH] patch: poppler-0.17 Squashed commit of the following: commit ad0adb0862960739f5dd2d699d2c75aee5e204d9 Author: Mukund Sivaraman Date: Thu Apr 21 13:57:13 2011 +0530 file-pdf-load: Update attribution, removing bogus copyright (cherry picked from commit e999122e0b20b6ccd6bde3ce039bb64068fc0019) commit b320fff7564fe254454df78c4af00e7da70fc790 Author: Nils Philippsen 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 83428bcdc84a08a8b59e9a88cad2288f6a1edf45 Author: Nils Philippsen 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 commit e51f6274e69c88f2ac269da7ae9cf6ff6ac6e1b3 Author: Nils Philippsen Date: Tue May 3 15:52:00 2011 +0200 libgimp: add gimp_layer_new_from_surface() and to enable that, make libgimp depend on Cairo. backported from: commit 374dd50c43cca559a4888224f8fd6322fb26115d Author: Michael Natterer Date: Wed Apr 20 23:58:00 2011 +0200 libgimp: add gimp_layer_new_from_surface() and to enable that, make libgimp depend on Cairo. --- configure.in | 2 + gimp.pc.in | 2 +- libgimp/Makefile.am | 2 +- libgimp/gimp.h | 1 + libgimp/gimplayer.c | 211 ++++++++++++++++++++++ libgimp/gimplayer.h | 8 + plug-ins/common/Makefile.am | 40 ++-- plug-ins/common/file-pdf.c | 368 ++++++++++++++++++++++++++++++++------- plug-ins/common/mkgen.pl | 2 +- plug-ins/file-faxg3/Makefile.am | 2 + plug-ins/help/Makefile.am | 2 + 11 files changed, 558 insertions(+), 82 deletions(-) diff --git a/configure.in b/configure.in index 41400f9..4338a13 100644 --- a/configure.in +++ b/configure.in @@ -113,8 +113,10 @@ AC_SUBST(GIMP_FULL_NAME) # These are used in the .pc files GLIB_REQUIRED_VERSION=glib_required_version GTK_REQUIRED_VERSION=gtk_required_version +CAIRO_REQUIRED_VERSION=cairo_required_version AC_SUBST(GLIB_REQUIRED_VERSION) AC_SUBST(GTK_REQUIRED_VERSION) +AC_SUBST(CAIRO_REQUIRED_VERSION) # The symbol GIMP_UNSTABLE is defined above for substitution in # Makefiles and conditionally defined here as a preprocessor symbol diff --git a/gimp.pc.in b/gimp.pc.in index 9d0058a..e61b438 100644 --- a/gimp.pc.in +++ b/gimp.pc.in @@ -12,6 +12,6 @@ gimplocaledir=@gimplocaledir@ Name: GIMP Description: GIMP Library Version: @GIMP_REAL_VERSION@ -Requires: glib-2.0 >= @GLIB_REQUIRED_VERSION@ +Requires: glib-2.0 >= @GLIB_REQUIRED_VERSION@ cairo >= @CAIRO_REQUIRED_VERSION@ Libs: -L${libdir} -lgimp-@GIMP_API_VERSION@ -lgimpmath-@GIMP_API_VERSION@ -lgimpconfig-@GIMP_API_VERSION@ -lgimpcolor-@GIMP_API_VERSION@ -lgimpbase-@GIMP_API_VERSION@ @RT_LIBS@ Cflags: -I${includedir}/gimp-@GIMP_API_VERSION@ diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am index f61568d..6912b64 100644 --- a/libgimp/Makefile.am +++ b/libgimp/Makefile.am @@ -363,7 +363,7 @@ libgimpui_2_0_la_LDFLAGS = \ $(libgimpui_export_symbols) libgimpui_2_0_la_LIBADD = $(libgimp) $(libgimpwidgets) $(libgimpcolor) \ - $(libgimpbase) $(libgimpmodule) $(GTK_LIBS) $(RT_LIBS) + $(libgimpbase) $(libgimpmodule) $(CAIRO_LIBS) $(GTK_LIBS) $(RT_LIBS) libgimpui_2_0_la_DEPENDENCIES = $(gimpui_def) $(libgimp) $(libgimpwidgets) $(libgimpbase) diff --git a/libgimp/gimp.h b/libgimp/gimp.h index 156530f..096dc2d 100644 --- a/libgimp/gimp.h +++ b/libgimp/gimp.h @@ -22,6 +22,7 @@ #ifndef __GIMP_H__ #define __GIMP_H__ +#include #include #include diff --git a/libgimp/gimplayer.c b/libgimp/gimplayer.c index 719542a..5bee7c6 100644 --- a/libgimp/gimplayer.c +++ b/libgimp/gimplayer.c @@ -84,6 +84,217 @@ gimp_layer_copy (gint32 layer_ID) } /** + * GIMP_CAIRO_RGB24_GET_PIXEL: + * @s: pointer to the source buffer + * @r: red component + * @g: green component + * @b: blue component + * + * Gets a single pixel from a Cairo image surface in %CAIRO_FORMAT_RGB24. + * + * Since: GIMP 2.8 + **/ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define GIMP_CAIRO_RGB24_GET_PIXEL(s, r, g, b) \ + G_STMT_START { (b) = s[0]; (g) = s[1]; (r) = s[2]; } G_STMT_END +#else +#define GIMP_CAIRO_RGB24_GET_PIXEL(s, r, g, b) \ + G_STMT_START { (r) = s[1]; (g) = s[2]; (b) = s[3]; } G_STMT_END +#endif + +/** + * GIMP_CAIRO_ARGB32_GET_PIXEL: + * @s: pointer to the source buffer + * @r: red component, not pre-multiplied + * @g: green component, not pre-multiplied + * @b: blue component, not pre-multiplied + * @a: alpha component + * + * Gets a single pixel from a Cairo image surface in %CAIRO_FORMAT_ARGB32. + * + * Since: GIMP 2.8 + **/ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define GIMP_CAIRO_ARGB32_GET_PIXEL(s, r, g, b, a) \ + G_STMT_START { \ + const guint tb = (s)[0]; \ + const guint tg = (s)[1]; \ + const guint tr = (s)[2]; \ + const guint ta = (s)[3]; \ + (r) = (tr << 8) / (ta + 1); \ + (g) = (tg << 8) / (ta + 1); \ + (b) = (tb << 8) / (ta + 1); \ + (a) = ta; \ + } G_STMT_END +#else +#define GIMP_CAIRO_ARGB32_GET_PIXEL(s, r, g, b, a) \ + G_STMT_START { \ + const guint ta = (s)[0]; \ + const guint tr = (s)[1]; \ + const guint tg = (s)[2]; \ + const guint tb = (s)[3]; \ + (r) = (tr << 8) / (ta + 1); \ + (g) = (tg << 8) / (ta + 1); \ + (b) = (tb << 8) / (ta + 1); \ + (a) = ta; \ + } G_STMT_END +#endif + +/** + * gimp_layer_new_from_surface: + * @image_ID: The RGB image to which to add the layer. + * @name: The layer name. + * @cairo_surface_t: A Cairo image surface. + * @opacity: The layer opacity. + * @mode: The layer combination mode. + * @progress_start: start of progress + * @progress_end: end of progress + * + * Create a new layer from a #cairo_surface_t. + * + * This procedure creates a new layer from the given + * #cairo_surface_t. The image has to be an RGB image and just like + * with gimp_layer_new() you will still need to add the layer to it. + * + * If you pass @progress_end > @progress_start to this function, + * gimp_progress_update() will be called for. You have to call + * gimp_progress_init() beforehand then. + * + * Returns: The newly created layer. + * + * Since: GIMP 2.8 + */ +gint32 +gimp_layer_new_from_surface (gint32 image_ID, + const gchar *name, + cairo_surface_t *surface, + gdouble opacity, + GimpLayerModeEffects mode, + gdouble progress_start, + gdouble progress_end) +{ + GimpDrawable *drawable; + GimpPixelRgn rgn; + const guchar *pixels; + gpointer pr; + gint32 layer; + cairo_format_t format; + gint width; + gint height; + gint rowstride; + gdouble range = progress_end - progress_start; + guint count = 0; + guint done = 0; + + g_return_val_if_fail (surface != NULL, -1); + g_return_val_if_fail (cairo_surface_get_type (surface) == + CAIRO_SURFACE_TYPE_IMAGE, -1); + + if (gimp_image_base_type (image_ID) != GIMP_RGB) + { + g_warning ("gimp_layer_new_from_surface() needs an RGB image"); + return -1; + } + + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); + format = cairo_image_surface_get_format (surface); + + if (format != CAIRO_FORMAT_ARGB32 && + format != CAIRO_FORMAT_RGB24) + { + g_warning ("gimp_layer_new_from_surface() assumes that surface is RGB"); + return -1; + } + + layer = gimp_layer_new (image_ID, name, width, height, + format == CAIRO_FORMAT_RGB24 ? + GIMP_RGB_IMAGE : GIMP_RGBA_IMAGE, + opacity, mode); + + if (layer == -1) + return -1; + + drawable = gimp_drawable_get (layer); + + gimp_pixel_rgn_init (&rgn, drawable, 0, 0, width, height, TRUE, FALSE); + + rowstride = cairo_image_surface_get_stride (surface); + pixels = cairo_image_surface_get_data (surface); + + for (pr = gimp_pixel_rgns_register (1, &rgn); + pr != NULL; + pr = gimp_pixel_rgns_process (pr)) + { + const guchar *src = pixels + rgn.y * rowstride + rgn.x * 4; + guchar *dest = rgn.data; + gint y; + + switch (format) + { + case CAIRO_FORMAT_RGB24: + for (y = 0; y < rgn.h; y++) + { + const guchar *s = src; + guchar *d = dest; + gint w = rgn.w; + + while (w--) + { + GIMP_CAIRO_RGB24_GET_PIXEL (s, d[0], d[1], d[2]); + + s += 4; + d += 3; + } + + src += rowstride; + dest += rgn.rowstride; + } + break; + + case CAIRO_FORMAT_ARGB32: + for (y = 0; y < rgn.h; y++) + { + const guchar *s = src; + guchar *d = dest; + gint w = rgn.w; + + while (w--) + { + GIMP_CAIRO_ARGB32_GET_PIXEL (s, d[0], d[1], d[2], d[3]); + + s += 4; + d += 4; + } + + src += rowstride; + dest += rgn.rowstride; + } + break; + + default: + break; + } + + if (range > 0.0) + { + done += rgn.h * rgn.w; + + if (count++ % 32 == 0) + gimp_progress_update (progress_start + + (gdouble) done / (width * height) * range); + } + } + + if (range > 0.0) + gimp_progress_update (progress_end); + + gimp_drawable_detach (drawable); + + return layer; +} + +/** * gimp_layer_get_preserve_trans: * @layer_ID: The layer. * diff --git a/libgimp/gimplayer.h b/libgimp/gimplayer.h index cbef025..32d9525 100644 --- a/libgimp/gimplayer.h +++ b/libgimp/gimplayer.h @@ -35,6 +35,14 @@ gint32 gimp_layer_new (gint32 image_ID, gdouble opacity, GimpLayerModeEffects mode); gint32 gimp_layer_copy (gint32 layer_ID); +gint32 gimp_layer_new_from_surface (gint32 image_ID, + const gchar *name, + cairo_surface_t *surface, + gdouble opacity, + GimpLayerModeEffects mode, + gdouble progress_start, + gdouble progress_end); + #ifndef GIMP_DISABLE_DEPRECATED gboolean gimp_layer_get_preserve_trans (gint32 layer_ID); diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am index d58ecee..612a3e0 100644 --- a/plug-ins/common/Makefile.am +++ b/plug-ins/common/Makefile.am @@ -250,7 +250,7 @@ animation_optimize_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -279,7 +279,7 @@ antialias_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -324,7 +324,7 @@ blur_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -595,7 +595,7 @@ contrast_normalize_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -624,7 +624,7 @@ contrast_stretch_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -637,7 +637,7 @@ contrast_stretch_hsv_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -666,7 +666,7 @@ crop_auto_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -679,7 +679,7 @@ crop_zealous_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -868,7 +868,7 @@ edge_laplace_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -978,7 +978,7 @@ file_compressor_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -1007,7 +1007,7 @@ file_desktop_link_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -1052,7 +1052,7 @@ file_gif_load_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -1097,7 +1097,7 @@ file_glob_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -1543,7 +1543,7 @@ gradient_map_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -1572,7 +1572,7 @@ guillotine_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -2052,7 +2052,7 @@ rotate_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -2100,7 +2100,7 @@ semi_flatten_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -2289,7 +2289,7 @@ tile_seamless_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -2350,7 +2350,7 @@ value_invert_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) @@ -2443,7 +2443,7 @@ web_browser_LDADD = \ $(libgimpconfig) \ $(libgimpcolor) \ $(libgimpbase) \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(CAIRO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) diff --git a/plug-ins/common/file-pdf.c b/plug-ins/common/file-pdf.c index a43b459..ae87a8b 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); +static gint32 layer_from_surface (gint32 image, + const gchar *layer_name, + gint position, + cairo_surface_t *surface, + 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; + cairo_surface_t *surface = NULL; /* Possibly retrieve last settings */ gimp_get_data (LOAD_PROC, &loadvals); @@ -455,20 +463,23 @@ 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); + + surface = get_thumb_surface (doc, 0, param[1].data.d_int32); + g_object_unref (doc); } - if (pixbuf) + if (surface) { - image = gimp_image_new (gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), + image = gimp_image_new (cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface), GIMP_RGB); gimp_image_undo_disable (image); - layer_from_pixbuf (image, "thumbnail", 0, pixbuf, 0.0, 1.0); - g_object_unref (pixbuf); + layer_from_surface (image, "thumbnail", 0, surface, 0.0, 1.0); + cairo_surface_destroy (surface); gimp_image_undo_enable (image); gimp_image_clean_all (image); @@ -548,24 +559,260 @@ 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, - gint position, - GdkPixbuf *pixbuf, - gdouble progress_start, - gdouble progress_scale) +layer_from_surface (gint32 image, + const gchar *layer_name, + gint position, + cairo_surface_t *surface, + gdouble progress_start, + gdouble progress_scale) { - gint32 layer = gimp_layer_new_from_pixbuf (image, layer_name, pixbuf, - 100.0, GIMP_NORMAL_MODE, - progress_start, - progress_start + progress_scale); + gint32 layer = gimp_layer_new_from_surface (image, layer_name, surface, + 100.0, GIMP_NORMAL_MODE, + progress_start, + progress_start + progress_scale); gimp_image_add_layer (image, layer, position); 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; +} + +#if 0 + +/* This is currently unused, but we'll have it here in case the military + wants it. */ + +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; +} + +#endif + static gint32 load_image (PopplerDocument *doc, const gchar *filename, @@ -597,9 +844,9 @@ load_image (PopplerDocument *doc, gdouble page_width; gdouble page_height; - GdkPixbuf *buf; - gint width; - gint height; + cairo_surface_t *surface; + gint width; + gint height; page = poppler_document_get_page (doc, pages->pages[i]); @@ -627,15 +874,13 @@ load_image (PopplerDocument *doc, gimp_image_set_resolution (image_ID, resolution, resolution); } - buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); + surface = render_page_to_surface (page, width, height, scale); - poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf); - - layer_from_pixbuf (image_ID, page_label, i, buf, - doc_progress, 1.0 / pages->n_pages); + layer_from_surface (image_ID, page_label, i, surface, + doc_progress, 1.0 / pages->n_pages); g_free (page_label); - g_object_unref (buf); + cairo_surface_destroy (surface); doc_progress = (double) (i + 1) / pages->n_pages; gimp_progress_update (doc_progress); @@ -676,30 +921,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 +949,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 +1019,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); diff --git a/plug-ins/common/mkgen.pl b/plug-ins/common/mkgen.pl index b0cd786..25ea7a7 100755 --- a/plug-ins/common/mkgen.pl +++ b/plug-ins/common/mkgen.pl @@ -131,7 +131,7 @@ foreach (sort keys %plugins) { if (exists $plugins{$_}->{ui}) { $glib = "\$(GTK_LIBS)" } else { - $glib = "\$(GLIB_LIBS)" + $glib = "\$(GLIB_LIBS) \$(CAIRO_LIBS)" } my $optlib = ""; diff --git a/plug-ins/file-faxg3/Makefile.am b/plug-ins/file-faxg3/Makefile.am index ac61d86..694127f 100644 --- a/plug-ins/file-faxg3/Makefile.am +++ b/plug-ins/file-faxg3/Makefile.am @@ -25,6 +25,7 @@ file_faxg3_SOURCES = \ INCLUDES = \ -I$(top_srcdir) \ + $(CAIRO_CFLAGS) \ $(GLIB_CFLAGS) \ -I$(includedir) @@ -34,6 +35,7 @@ LDADD = \ $(libgimpcolor) \ $(libgimpbase) \ $(libgimpmath) \ + $(CAIRO_LIBS) \ $(GLIB_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) diff --git a/plug-ins/help/Makefile.am b/plug-ins/help/Makefile.am index c5f49ae..b72d368 100644 --- a/plug-ins/help/Makefile.am +++ b/plug-ins/help/Makefile.am @@ -39,6 +39,7 @@ help_SOURCES = help.c INCLUDES = \ -I$(top_srcdir) \ + $(CAIRO_CFLAGS) \ $(GIO_CFLAGS) \ -I$(includedir) @@ -49,6 +50,7 @@ LDADD = \ $(libgimpcolor) \ $(libgimpbase) \ $(libgimpmath) \ + $(CAIRO_LIBS) \ $(GIO_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) -- 1.7.5