diff -urN gtk+-2.10.9.orig/config.h.in gtk+-2.10.9-integer-pixops/config.h.in --- gtk+-2.10.9.orig/config.h.in 2007-01-22 09:01:23.000000000 -0700 +++ gtk+-2.10.9-integer-pixops/config.h.in 2007-02-10 12:15:39.000000000 -0700 @@ -259,3 +259,7 @@ /* Define to `int' if doesn't define. */ #undef uid_t + +/* Define to use integer math rather than floating point where possible. */ +#undef ENABLE_INTEGER_PIXOPS + diff -urN gtk+-2.10.9.orig/configure.in gtk+-2.10.9-integer-pixops/configure.in --- gtk+-2.10.9.orig/configure.in 2007-01-22 08:59:41.000000000 -0700 +++ gtk+-2.10.9-integer-pixops/configure.in 2007-02-10 12:15:39.000000000 -0700 @@ -203,6 +203,15 @@ [AC_HELP_STRING([--disable-rebuilds], [disable all source autogeneration rules])],, [enable_rebuilds=yes]) +AC_ARG_ENABLE(integer-pixops, + [AC_HELP_STRING([--enable-integer-pixops], + [use integer math where possible])],, + [enable_integer_pixops=no]) + +if test "x$enable_integer_pixops" = "xyes"; then + AC_DEFINE(ENABLE_INTEGER_PIXOPS) +fi + AC_ARG_ENABLE(visibility, [AC_HELP_STRING([--disable-visibility], [don't use ELF visibility attributes])],, diff -urN gtk+-2.10.9.orig/gdk-pixbuf/pixops/pixops.c gtk+-2.10.9-integer-pixops/gdk-pixbuf/pixops/pixops.c --- gtk+-2.10.9.orig/gdk-pixbuf/pixops/pixops.c 2007-01-22 08:50:43.000000000 -0700 +++ gtk+-2.10.9-integer-pixops/gdk-pixbuf/pixops/pixops.c 2007-02-12 01:00:23.000000000 -0700 @@ -28,21 +28,42 @@ #define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS)-1) #define SCALE_SHIFT 16 +/* TODO: Add a FLOOR() and CEIL() macro to handle normalized values) */ +/* TODO: Get rid of standard C numeric types (ie. int). Replace with glib types */ +#ifdef ENABLE_INTEGER_PIXOPS +/* The bigger the value of FRAC is, the better the accuracy. Be wary of + overflows, though */ +#define FRAC 0x10000ULL +#define NORMALIZE(d) (d * FRAC) +#define UNNORMALIZE(t,i) ((t)(i) / FRAC) +#define FLOOR(i) (int)((i) / FRAC) +#define CEIL(i) (((i) - 1) / FRAC + 1) +#define DOUBLE_TYPE gint32 +#define BIG_DOUBLE_TYPE gint64 +#else +#define NORMALIZE(d) (d) +#define UNNORMALIZE(t,i) (t)(i) +#define FLOOR(i) floor(i) +#define CEIL(i) ceil(i) +#define DOUBLE_TYPE double +#define BIG_DOUBLE_TYPE double +#endif + typedef struct _PixopsFilter PixopsFilter; typedef struct _PixopsFilterDimension PixopsFilterDimension; struct _PixopsFilterDimension { int n; - double offset; - double *weights; + BIG_DOUBLE_TYPE offset; + DOUBLE_TYPE *weights; }; struct _PixopsFilter { PixopsFilterDimension x; PixopsFilterDimension y; - double overall_alpha; + gint32 overall_alpha; /* Normalized: alpha * 255; Not sure why original devs chose 255 */ }; typedef guchar *(*PixopsLineFunc) (int *weights, int n_x, int n_y, @@ -86,13 +107,13 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y) + DOUBLE_TYPE scale_x, + DOUBLE_TYPE scale_y) { int i; int x; - int x_step = (1 << SCALE_SHIFT) / scale_x; - int y_step = (1 << SCALE_SHIFT) / scale_y; + int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x; + int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y; int xmax, xstart, xstop, x_pos, y_pos; const guchar *p; @@ -175,14 +196,14 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + DOUBLE_TYPE scale_x, + DOUBLE_TYPE scale_y, int overall_alpha) { int i; int x; - int x_step = (1 << SCALE_SHIFT) / scale_x; - int y_step = (1 << SCALE_SHIFT) / scale_y; + int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x; + int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y; int xmax, xstart, xstop, x_pos, y_pos; const guchar *p; unsigned int a0; @@ -260,8 +281,8 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + DOUBLE_TYPE scale_x, + DOUBLE_TYPE scale_y, int overall_alpha, int check_x, int check_y, @@ -271,8 +292,8 @@ { int i, j; int x; - int x_step = (1 << SCALE_SHIFT) / scale_x; - int y_step = (1 << SCALE_SHIFT) / scale_y; + int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x; + int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y; int r1, g1, b1, r2, g2, b2; int check_shift = get_check_shift (check_size); int xmax, xstart, xstop, x_pos, y_pos; @@ -977,9 +998,9 @@ int n_x, int n_y, int total, - double overall_alpha) + gint32 overall_alpha) { - int correction = (int)(0.5 + 65536 * overall_alpha) - total; + int correction = (int)(0.5 + 65536 / 255 * overall_alpha) - total; int remaining, c, d, i; if (correction != 0) @@ -1009,7 +1030,7 @@ for (i_offset=0; i_offset < SUBSAMPLE; i_offset++) for (j_offset=0; j_offset < SUBSAMPLE; j_offset++) { - double weight; + DOUBLE_TYPE weight; int *pixel_weights = weights + ((i_offset*SUBSAMPLE) + j_offset) * n_x * n_y; int total = 0; int i, j; @@ -1017,13 +1038,15 @@ for (i=0; i < n_y; i++) for (j=0; j < n_x; j++) { - weight = filter->x.weights[(j_offset * n_x) + j] * + weight = UNNORMALIZE(DOUBLE_TYPE, filter->x.weights[(j_offset * n_x) + j] * filter->y.weights[(i_offset * n_y) + i] * - filter->overall_alpha * 65536 + 0.5; + filter->overall_alpha * 65536 / 255) + NORMALIZE(0.5); + /* Wonder how I should treat the "+ 0.5" for scientific + rouding off */ - total += (int)weight; + total += UNNORMALIZE(int, weight); - *(pixel_weights + n_x * i + j) = weight; + *(pixel_weights + n_x * i + j) = UNNORMALIZE(int, weight); } correct_total (pixel_weights, n_x, n_y, total, filter->overall_alpha); @@ -1047,8 +1070,8 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + DOUBLE_TYPE scale_x, + DOUBLE_TYPE scale_y, int check_x, int check_y, int check_size, @@ -1064,12 +1087,13 @@ guchar **line_bufs = g_new (guchar *, filter->y.n); int *filter_weights = make_filter_table (filter); - int x_step = (1 << SCALE_SHIFT) / scale_x; /* X step in source (fixed point) */ - int y_step = (1 << SCALE_SHIFT) / scale_y; /* Y step in source (fixed point) */ + int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x; /* X step in source (fixed point) */ + int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y; /* Y step in source (fixed point) */ int check_shift = check_size ? get_check_shift (check_size) : 0; - int scaled_x_offset = floor (filter->x.offset * (1 << SCALE_SHIFT)); + /* Possible overflow when scale-shifting which is why offset is BIG_DOUBLE_TYPE */ + int scaled_x_offset = FLOOR(filter->x.offset * (1 << SCALE_SHIFT)); /* Compute the index where we run off the end of the source buffer. The furthest * source pixel we access at index i is: @@ -1087,7 +1111,7 @@ int run_end_index = MYDIV (run_end_x + x_step - 1, x_step) - render_x0; run_end_index = MIN (run_end_index, render_x1 - render_x0); - y = render_y0 * y_step + floor (filter->y.offset * (1 << SCALE_SHIFT)); + y = render_y0 * y_step + FLOOR(filter->y.offset * (1 << SCALE_SHIFT)); for (i = 0; i < (render_y1 - render_y0); i++) { int dest_x; @@ -1180,37 +1204,37 @@ */ static void tile_make_weights (PixopsFilterDimension *dim, - double scale) + DOUBLE_TYPE scale) { - int n = ceil (1 / scale + 1); - double *pixel_weights = g_new (double, SUBSAMPLE * n); + int n = CEIL(NORMALIZE(NORMALIZE(1)) / scale + NORMALIZE(1)); /* Another possible overflow */ + DOUBLE_TYPE *pixel_weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n); int offset; int i; - + dim->n = n; - dim->offset = 0; + dim->offset = NORMALIZE(0); dim->weights = pixel_weights; for (offset = 0; offset < SUBSAMPLE; offset++) { - double x = (double)offset / SUBSAMPLE; - double a = x + 1 / scale; + DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE; + DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale; for (i = 0; i < n; i++) { - if (i < x) + if (NORMALIZE(i) < x) { - if (i + 1 > x) - *(pixel_weights++) = (MIN (i + 1, a) - x) * scale; + if (NORMALIZE(i + 1) > x) + *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - x) * scale); else - *(pixel_weights++) = 0; + *(pixel_weights++) = NORMALIZE(0); } else { - if (a > i) - *(pixel_weights++) = (MIN (i + 1, a) - i) * scale; + if (a > NORMALIZE(i)) + *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - i) * scale); else - *(pixel_weights++) = 0; + *(pixel_weights++) = NORMALIZE(0); } } } @@ -1222,41 +1246,44 @@ */ static void bilinear_magnify_make_weights (PixopsFilterDimension *dim, - double scale) + DOUBLE_TYPE scale) { - double *pixel_weights; + DOUBLE_TYPE *pixel_weights; int n; int offset; int i; - if (scale > 1.0) /* Linear */ + if (scale > NORMALIZE(1.0)) /* Linear */ { n = 2; - dim->offset = 0.5 * (1 / scale - 1); + dim->offset = NORMALIZE(NORMALIZE(0.5) / (scale - NORMALIZE(1))); } else /* Tile */ { - n = ceil (1.0 + 1.0 / scale); - dim->offset = 0.0; + n = CEIL(NORMALIZE(1.0) + NORMALIZE(NORMALIZE(1.0)) / scale); + dim->offset = NORMALIZE(0.0); } - + dim->n = n; - dim->weights = g_new (double, SUBSAMPLE * n); + dim->weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n); pixel_weights = dim->weights; for (offset=0; offset < SUBSAMPLE; offset++) { - double x = (double)offset / SUBSAMPLE; + DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE; - if (scale > 1.0) /* Linear */ + if (scale > NORMALIZE(1.0)) /* Linear */ { for (i = 0; i < n; i++) - *(pixel_weights++) = (((i == 0) ? (1 - x) : x) / scale) * scale; + /* In the original, what is the point of dividing by scale then multiplying by scale? */ + /* *(pixel_weights++) = (((i == 0) ? (1 - x) : x) / scale) * scale;*/ + /* *(pixel_weights++) = i == 0 ? NORMALIZE(1) - x : x; */ + *(pixel_weights++) = (((i == 0) ? NORMALIZE(1) - x : x) / scale) * scale; } else /* Tile */ { - double a = x + 1 / scale; + DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale; /* x * ---------|--.-|----|--.-|------- SRC @@ -1264,19 +1291,19 @@ */ for (i = 0; i < n; i++) { - if (i < x) + if (NORMALIZE(i) < x) { - if (i + 1 > x) - *(pixel_weights++) = (MIN (i + 1, a) - x) * scale; + if (NORMALIZE(i + 1) > x) + *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - x) * scale); else - *(pixel_weights++) = 0; + *(pixel_weights++) = NORMALIZE(0); } else { - if (a > i) - *(pixel_weights++) = (MIN (i + 1, a) - i) * scale; + if (a > NORMALIZE(i)) + *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - i) * scale); else - *(pixel_weights++) = 0; + *(pixel_weights++) = NORMALIZE(0); } } } @@ -1291,14 +1318,14 @@ * We combine two of these to compute the convolution of * a box filter with a triangular spike. */ -static double -linear_box_half (double b0, double b1) +static DOUBLE_TYPE +linear_box_half (DOUBLE_TYPE b0, DOUBLE_TYPE b1) { - double a0, a1; - double x0, x1; + DOUBLE_TYPE a0, a1; + DOUBLE_TYPE x0, x1; - a0 = 0.; - a1 = 1.; + a0 = NORMALIZE(0.); + a1 = NORMALIZE(1.); if (a0 < b0) { @@ -1308,7 +1335,7 @@ x1 = MIN (a1, b1); } else - return 0; + return NORMALIZE(0); } else { @@ -1318,10 +1345,10 @@ x1 = MIN (a1, b1); } else - return 0; + return NORMALIZE(0); } - return 0.5 * (x1*x1 - x0*x0); + return UNNORMALIZE(DOUBLE_TYPE, NORMALIZE(0.5) * UNNORMALIZE(DOUBLE_TYPE, (x1*x1 - x0*x0))); } /* Compute weights for reconstructing with bilinear @@ -1329,28 +1356,28 @@ */ static void bilinear_box_make_weights (PixopsFilterDimension *dim, - double scale) + DOUBLE_TYPE scale) { - int n = ceil (1/scale + 3.0); - double *pixel_weights = g_new (double, SUBSAMPLE * n); - double w; + int n = CEIL(NORMALIZE(NORMALIZE(1))/scale + NORMALIZE(3.0)); + DOUBLE_TYPE *pixel_weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n); + DOUBLE_TYPE w; int offset, i; - dim->offset = -1.0; + dim->offset = NORMALIZE(-1.0); dim->n = n; dim->weights = pixel_weights; for (offset = 0; offset < SUBSAMPLE; offset++) { - double x = (double)offset / SUBSAMPLE; - double a = x + 1 / scale; + DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE; + DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale; for (i = 0; i < n; i++) { - w = linear_box_half (0.5 + i - a, 0.5 + i - x); - w += linear_box_half (1.5 + x - i, 1.5 + a - i); + w = linear_box_half (NORMALIZE(0.5) + NORMALIZE(i) - a, NORMALIZE(0.5) + NORMALIZE(i) - x); + w += linear_box_half (NORMALIZE(1.5) - NORMALIZE(i) + x, NORMALIZE(1.5) - NORMALIZE(i) + a); - *(pixel_weights++) = w * scale; + *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, w * scale); } } } @@ -1358,8 +1385,8 @@ static void make_weights (PixopsFilter *filter, PixopsInterpType interp_type, - double scale_x, - double scale_y) + DOUBLE_TYPE scale_x, + DOUBLE_TYPE scale_y) { switch (interp_type) { @@ -1399,8 +1426,8 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + double scale_x_d, + double scale_y_d, PixopsInterpType interp_type, int overall_alpha, int check_x, @@ -1409,6 +1436,8 @@ guint32 color1, guint32 color2) { + DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d); + DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d); PixopsFilter filter; PixopsLineFunc line_func; @@ -1419,7 +1448,7 @@ g_return_if_fail (!(dest_channels == 3 && dest_has_alpha)); g_return_if_fail (!(src_channels == 3 && src_has_alpha)); - if (scale_x == 0 || scale_y == 0) + if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0)) return; if (!src_has_alpha && overall_alpha == 255) @@ -1427,7 +1456,7 @@ _pixops_scale (dest_buf, render_x0, render_y0, render_x1, render_y1, dest_rowstride, dest_channels, dest_has_alpha, src_buf, src_width, src_height, src_rowstride, src_channels, - src_has_alpha, scale_x, scale_y, interp_type); + src_has_alpha, UNNORMALIZE(double, scale_x), UNNORMALIZE(double, scale_y), interp_type); return; } @@ -1441,7 +1470,8 @@ return; } - filter.overall_alpha = overall_alpha / 255.; + /* filter.overall_alpha = overall_alpha / 255.; /* Why is it 255 instead of 256? */ + filter.overall_alpha = overall_alpha; make_weights (&filter, interp_type, scale_x, scale_y); #ifdef USE_MMX @@ -1501,11 +1531,13 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + double scale_x_d, + double scale_y_d, PixopsInterpType interp_type, int overall_alpha) { + DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d); + DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d); PixopsFilter filter; PixopsLineFunc line_func; @@ -1516,7 +1548,7 @@ g_return_if_fail (!(dest_channels == 3 && dest_has_alpha)); g_return_if_fail (!(src_channels == 3 && src_has_alpha)); - if (scale_x == 0 || scale_y == 0) + if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0)) return; if (!src_has_alpha && overall_alpha == 255) @@ -1524,7 +1556,7 @@ _pixops_scale (dest_buf, render_x0, render_y0, render_x1, render_y1, dest_rowstride, dest_channels, dest_has_alpha, src_buf, src_width, src_height, src_rowstride, src_channels, - src_has_alpha, scale_x, scale_y, interp_type); + src_has_alpha, UNNORMALIZE(double, scale_x), UNNORMALIZE(double, scale_y), interp_type); return; } @@ -1537,7 +1569,7 @@ return; } - filter.overall_alpha = overall_alpha / 255.; + filter.overall_alpha = overall_alpha; make_weights (&filter, interp_type, scale_x, scale_y); if (filter.x.n == 2 && filter.y.n == 2 && @@ -1578,10 +1610,12 @@ int src_rowstride, int src_channels, gboolean src_has_alpha, - double scale_x, - double scale_y, + double scale_x_d, + double scale_y_d, PixopsInterpType interp_type) { + DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d); + DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d); PixopsFilter filter; PixopsLineFunc line_func; @@ -1593,7 +1627,7 @@ g_return_if_fail (!(src_channels == 3 && src_has_alpha)); g_return_if_fail (!(src_has_alpha && !dest_has_alpha)); - if (scale_x == 0 || scale_y == 0) + if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0)) return; if (interp_type == PIXOPS_INTERP_NEAREST) @@ -1605,7 +1639,7 @@ return; } - filter.overall_alpha = 1.0; + filter.overall_alpha = 255; make_weights (&filter, interp_type, scale_x, scale_y); if (filter.x.n == 2 && filter.y.n == 2 && dest_channels == 3 && src_channels == 3)