Patch to enable compilation of GIMP 2.4.x with poppler >= 0.17

Plus other frigs to compile it on Debian jessie

Recently I suffered the misfortune of having my root filesystem eat itself. I recovered some of it, but not the important stuff - like the contents of /etc - so I decided to stop trying and instead just install Debian testing (currently jessie) on it in place of the unholy mixture of bits from every version of Ubuntu from hardy to trusty that I had had before. Ubuntu is getting to be too much of a pain in the arse these days anyway, plus all my other machines run straight Debian and it's much more friendly.

This, of course, meant that I had to find some way to install GIMP 2.4.x on it - the version currently in jessie is 2.8.6, and all versions from 2.6 on are shite. Sure you can get rid of the fucking horrendous UI changes in 2.6, such as having to have an empty image window open all the time for no fucking reason whatsoever, with the gimp-classic patch, which is fucking brilliant, but that still does not fix other, more minor, things they fucked up in 2.6+ and if I was going to be building a package in any case I figured I might as well build the one I really wanted.

So I downloaded the GIMP 2.4.7 source from lenny and tried to compile it...

This turned out to be not as easy as I would have liked. Possibly the most severe error was caused by poppler 0.17 having removed poppler_page_render_to_pixbuf() which broke the plugin for opening PDF files. Fortunately, I did not have to fuck around working out how to fix this myself. Googling around I found, in amongst all the other complaints from people whose packages had been similarly broken by the poppler maintainers being cunts, a patch to fix the problem on GIMP 2.6.11 in gentoo, and although the name of the source file has changed from poppler.c to file-pdf.c, the code in it seems to be nearly the same so it is still possible to apply the patch.

There were also two other errors caused by package maintainers randomly changing things for no reason. In gimpfont.c, it is necessary to change #include <freetype/tttables.h> to #include <freetype2/tttables.h> as the path to that header file has changed, and in uri-backend-libcurl.c it is necessary to remove #include <curl/types.h> altogether as that header file no longer exists - fortunately the GIMP source seems to be able to find everything it needs in the header files which do still exist, so the simple fix is possible.

Update: ...although whatever type-checking is done with the current curl libraries/headers does not bleeding work, so while the package can be compiled without errors the URI plugin crashes after downloading the file. The cure for this is to change the type of response_code in uri-backend-libcurl.c from gint to long.

A patch file for these three changes is included at the bottom of this page.

There were also a couple of other problems which I would class as fuckups rather than as errors. The first of these relates to the "format security" thing with printf() and similar functions - ie. the thing whereby if you have a call of the form printf(some_string); rather than printf("%s", some_string); and some_string contains unsanitised user-supplied input, there is potential to fuck things up. C has had that for 40 years and it hasn't been a problem, but looking on Google it seems that about 2 years ago there was a massive outburst of whining about it and since then most Linux distributions have been forcing all compilations to be done with -Werror=format-security set, which breaks pretty well every bit of source written before they started doing that. Fucksake.

The GIMP source contains fuck loads of calls of the form printf(some_string); and due to the way it has been formatted it is not possible to simply grep for them. After the compilation had bombed about 15 times on these calls I got fucked off with changing them and decided to just turn the bloody thing off. On Debian this is nice and easy - all that is needed is to create a file ~/.config/dpkg/buildflags.conf which contains:

STRIP CFLAGS -Werror=format-security STRIP CXXFLAGS -Werror=format-security SET CPPFLAGS -D_FORTIFY_SOURCE=1

This takes effect on all compilations undertaken with dpkg-buildpackage. The first two lines make sure they are done without that bastard error flag set. The third line tones down some other newly-introduced buckfuggery - as standard that flag is set to 2, not 1 - and is probably not strictly necessary, but it is said to reduce the risk of yet more shit going wrong so I thought I'd stick it in there while I was at it.

The second fuckup turned out to be a complete dog's cunt. As is nearly always the case, the actual compilation of the code is preceded by an automatic configuration step which works out what sort of system it's being built on and generates appropriate Makefiles and compiler/linker flags etc. 99.9% of the time these things Just Work and they're bloody great. Unfortunately this turned out to be one of the 0.1% of cases where it doesn't work, and it was a right fucking shit.

What it was doing was getting the linker flags wrong for some - but not all - subdirectories of the source tree, which caused some linking operations to fail with undefined references to symbols in libgobject-2.0, libglib-2.0 and libm. But worse than this, it also fought like a bastard to keep them wrong. The standard frig of setting LDFLAGS=-lgobject-2.0 -lglib-2.0 -lm did not work, no matter where I tried setting it - whether in debian/rules, in the Makefile sources for the affected subdirectories, in ~/.config/dpkg/buildflags.conf - some fucking cunt piece of code stripped the fucking flags out again. Indeed, it gave a very strong impression of doing this out of active malice, since it didn't necessarily strip all three of the extra flags out - often, it just removed the specific one which needed to be set to enable that particular linking operation to succeed. Absolute fucking wanker or what.

Automatic configuration systems contain some of the most brain-melting code I have ever come across and I seriously could not be fucked with trying to sort out exactly where the cuntery was occurring and removing it. So I took a sledgehammer to it; I removed the symlink from /usr/bin/ld to /usr/bin/ld.bfd, and replaced it with a symlink to a script ldfrig which contained this:

#!/bin/bash echo /usr/bin/ld.bfd ${*} -lgobject-2.0 -lglib-2.0 -lm exec /usr/bin/ld.bfd ${*} -lgobject-2.0 -lglib-2.0 -lm

That put my custom flags beyond the reach of the wanker code and fixed the problem. Of course, it did also result in fuck loads of warnings about the possibility of being able to remove a useless dependency on libsomethingorother were thisandthat not linked against it despite using none of its symbols, but since these only applied to specific subsections of the code and the package as a whole would still require those dependencies, I wasn't bothered. In any case there were just as many such warnings in respect of other libraries which were caused by what was in the code already and were nothing to do with me.

Anyway, it fucking worked in the end!

Here follows the patch for the three changes I had to make to the C source files...

Fix compilation errors with gimp 2.4.x and poppler >= 0.17 : gimp-2.4.7-jessie.patch.gz

diff -ur gimp-2.4.7.orig/app/text/gimpfont.c gimp-2.4.7/app/text/gimpfont.c --- gimp-2.4.7.orig/app/text/gimpfont.c 2008-07-10 11:29:44.000000000 +0100 +++ gimp-2.4.7/app/text/gimpfont.c 2013-12-23 06:57:15.000000000 +0000 @@ -29,7 +29,7 @@ #define PANGO_ENABLE_ENGINE 1 /* Argh */ #include <pango/pango-ot.h> -#include <freetype/tttables.h> +#include <freetype2/tttables.h> #include "text-types.h" diff -ur gimp-2.4.7.orig/plug-ins/common/poppler.c gimp-2.4.7/plug-ins/common/poppler.c --- gimp-2.4.7.orig/plug-ins/common/poppler.c 2008-07-10 11:31:57.000000000 +0100 +++ gimp-2.4.7/plug-ins/common/poppler.c 2013-12-23 21:30:15.000000000 +0000 @@ -3,6 +3,11 @@ * poppler.c - PDF file loader * * Copyright (C) 2005 Nathan Summers + * + * Patch to fix compilation with poppler >= 0.17 filched from + * http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/media-gfx/gimp/files/gimp-2.6.11-poppler-0.17.patch + * file-pdf.c in 2.6.11 seems to be the same code as poppler.c in 2.4.7 + * and the patch seems to fit... * * 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 @@ -77,7 +82,11 @@ static PopplerDocument * open_document (const gchar *filename); -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); @@ -432,6 +441,7 @@ gdouble height = 0; gdouble scale; gint32 image = -1; + gint num_pages = 0; GdkPixbuf *pixbuf = NULL; /* Possibly retrieve last settings */ @@ -448,9 +458,9 @@ poppler_page_get_size (page, &width, &height); 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); } @@ -534,6 +544,187 @@ 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, @@ -552,6 +743,54 @@ 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, @@ -583,7 +822,7 @@ gdouble page_width; gdouble page_height; - GdkPixbuf *buf; + GdkPixbuf *pixbuf; gint width; gint height; @@ -613,15 +852,13 @@ 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); @@ -662,30 +899,23 @@ 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; @@ -698,15 +928,28 @@ 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; } @@ -755,7 +998,7 @@ idle_data->page_no = i; /* FIXME get preferred size from somewhere? */ - idle_data->pixbuf = get_thumbnail (thread_data->document, i, + idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i, THUMBNAIL_SIZE); g_idle_add (idle_set_thumbnail, idle_data); diff -ur gimp-2.4.7.orig/plug-ins/uri/uri-backend-libcurl.c gimp-2.4.7/plug-ins/uri/uri-backend-libcurl.c --- gimp-2.4.7.orig/plug-ins/uri/uri-backend-libcurl.c 2008-07-10 11:31:39.000000000 +0100 +++ gimp-2.4.7/plug-ins/uri/uri-backend-libcurl.c 2013-12-23 22:36:40.000000000 +0000 @@ -24,7 +24,9 @@ #include <stdio.h> #include <curl/curl.h> -#include <curl/types.h> +/* This no longer exists + * #include <curl/types.h> + */ #include <curl/easy.h> #include <libgimp/gimp.h> @@ -150,7 +152,7 @@ FILE *out_file; CURL *curl_handle; CURLcode result; - gint response_code; + long response_code; gimp_progress_init (_("Connecting to server")); @@ -197,7 +199,7 @@ g_set_error (error, 0, 0, _("Opening '%s' for reading resulted in HTTP " "response code: %d"), - uri, response_code); + uri, (gint)response_code); curl_easy_cleanup (curl_handle); return FALSE; }




Back to Pigeon's Nest


Be kind to pigeons




Valid HTML 4.01!