From 6707a8969f17f81550b2ecb00bb32194c4ccc3e6 Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Mon, 12 Oct 1998 04:33:20 +0000 Subject: [PATCH] Speed up cubism by 2x (I think) and mosaic something along the same vein. Speed up cubism by 2x (I think) and mosaic something along the same vein. --- plug-ins/common/cubism.c | 131 ++++++++++++++++++++++------------- plug-ins/common/mosaic.c | 144 ++++++++++++++++++++++++++------------- plug-ins/cubism/cubism.c | 131 ++++++++++++++++++++++------------- plug-ins/mosaic/mosaic.c | 144 ++++++++++++++++++++++++++------------- 4 files changed, 364 insertions(+), 186 deletions(-) diff --git a/plug-ins/common/cubism.c b/plug-ins/common/cubism.c index 6ce1e59242..6e3a18c295 100644 --- a/plug-ins/common/cubism.c +++ b/plug-ins/common/cubism.c @@ -17,6 +17,7 @@ * * You can contact me at quartic@polloux.fciencias.unam.mx * You can contact the original The Gimp authors at gimp@xcf.berkeley.edu + * Speedups by Elliot Lee */ @@ -96,7 +97,7 @@ static void randomize_indices (gint count, static gdouble fp_rand (gdouble val); static gint int_rand (gint val); static gdouble calc_alpha_blend (gdouble * vec, - gdouble dist, + gdouble one_over_dist, gdouble x, gdouble y); static void polygon_add_point (Polygon * poly, @@ -501,6 +502,27 @@ render_cubism (GDrawable *drawable) free (random_indices); } +G_INLINE_FUNC gdouble +calc_alpha_blend (gdouble *vec, + gdouble one_over_dist, + gdouble x, + gdouble y) +{ + gdouble r; + + if (!one_over_dist) + return 1.0; + else + { + r = (vec[0] * x + vec[1] * y) * one_over_dist; + if (r < 0.2) + r = 0.2; + else if (r > 1.0) + r = 1.0; + } + return r; +} + static void fill_poly_color (Polygon *poly, GDrawable *drawable, @@ -514,22 +536,23 @@ fill_poly_color (Polygon *poly, gint min_x, min_y; gint max_x, max_y; gint size_x, size_y; - gint * max_scanlines; - gint * min_scanlines; - gint * vals; + gint * max_scanlines, *max_scanlines_iter, *max_scanlines_end; + gint * min_scanlines, *min_scanlines_iter, *min_scanlines_end; gint val; gint alpha; gint bytes; guchar buf[4]; - gint b, i, j, k, x, y; + gint i, j, x, y; gdouble sx, sy; gdouble ex, ey; gdouble xx, yy; gdouble vec[2]; - gdouble dist; + gdouble dist, one_over_dist; gint supersample; gint supersample2; gint x1, y1, x2, y2; + gint *vals, *vals_iter, *vals_end; + gint pixel_gen_on_next_pass = -1; sx = poly->pts[0].x; sy = poly->pts[0].y; @@ -539,9 +562,11 @@ fill_poly_color (Polygon *poly, dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); if (dist > 0.0) { - vec[0] = (ex - sx) / dist; - vec[1] = (ey - sy) / dist; - } + one_over_dist = 1/dist; + vec[0] = (ex - sx) * one_over_dist; + vec[1] = (ey - sy) * one_over_dist; + } else + one_over_dist = 0.0; supersample = SUPERSAMPLE; supersample2 = SQR (supersample); @@ -558,20 +583,37 @@ fill_poly_color (Polygon *poly, size_y = (max_y - min_y) * supersample; size_x = (max_x - min_x) * supersample; - min_scanlines = (gint *) malloc (sizeof (gint) * size_y); - max_scanlines = (gint *) malloc (sizeof (gint) * size_y); + min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); + max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); for (i = 0; i < size_y; i++) { min_scanlines[i] = max_x * supersample; max_scanlines[i] = min_x * supersample; } - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; + if(poly->npts) { + gint poly_npts = poly->npts; + Vertex *curptr; + + xs = (gint) (poly->pts[poly_npts-1].x); + ys = (gint) (poly->pts[poly_npts-1].y); + xe = (gint) poly->pts[0].x; + ye = (gint) poly->pts[0].y; + + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; + + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + + for(i = 1, curptr = &poly->pts[0]; i < poly_npts; i++) { + xs = (gint) curptr->x; + ys = (gint) curptr->y; + curptr++; + xe = (gint) curptr->x; + ye = (gint) curptr->y; xs *= supersample; ys *= supersample; @@ -581,20 +623,22 @@ fill_poly_color (Polygon *poly, convert_segment (xs, ys, xe, ye, min_y * supersample, min_scanlines, max_scanlines); } + } gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, TRUE); vals = (gint *) malloc (sizeof (gint) * size_x); - for (i = 0; i < size_y; i++) + for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++) { - if (! (i % supersample)) + if (! (i % supersample)) { memset (vals, 0, sizeof (gint) * size_x); + } - yy = (gdouble) i / (gdouble) supersample + min_y; + yy = (gdouble)i / (gdouble)supersample + min_y; - for (j = min_scanlines[i]; j < max_scanlines[i]; j++) + for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++) { x = j - min_x * supersample; vals[x] += 255; @@ -612,21 +656,37 @@ fill_poly_color (Polygon *poly, if (x >= x1 && x < x2) { - val = 0; - for (k = 0; k < supersample; k++) - val += vals[j + k]; + for (val = 0, vals_iter = &vals[j], + vals_end = &vals_iter[supersample]; + vals_iter < vals_end; + vals_iter++) + val += *vals_iter; + val /= supersample2; if (val > 0) { xx = (gdouble) j / (gdouble) supersample + min_x; - alpha = (gint) (val * calc_alpha_blend (vec, dist, xx - sx, yy - sy)); + alpha = (gint) (val * calc_alpha_blend (vec, one_over_dist, xx - sx, yy - sy)); gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y); +#ifndef USE_READABLE_BUT_SLOW_CODE + { + guchar *buf_iter = buf, + *col_iter = col, + *buf_end = buf+bytes; + + for(; buf_iter < buf_end; buf_iter++, col_iter++) + *buf_iter = ((guint)(*col_iter * alpha) + + (((guint)*buf_iter) + * (256 - alpha))) >> 8; + } +#else /* original, pre-ECL code */ for (b = 0; b < bytes; b++) buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255; +#endif gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y); } } @@ -673,27 +733,6 @@ convert_segment (gint x1, } } -static gdouble -calc_alpha_blend (gdouble *vec, - gdouble dist, - gdouble x, - gdouble y) -{ - gdouble r; - - if (!dist) - return 1.0; - else - { - r = (vec[1] * y + vec[0] * x) / dist; - if (r < 0.2) - r = 0.2; - else if (r > 1.0) - r = 1.0; - } - return r; -} - static void randomize_indices (gint count, gint *indices) diff --git a/plug-ins/common/mosaic.c b/plug-ins/common/mosaic.c index b42a184e32..6a505b6477 100644 --- a/plug-ins/common/mosaic.c +++ b/plug-ins/common/mosaic.c @@ -20,6 +20,7 @@ * what appears to be a mosaic, composed of small primitives, * each of constant color and of an approximate size. * Copyright (C) 1996 Spencer Kimball + * Speedups by Elliot Lee */ #include @@ -887,23 +888,19 @@ find_gradients (GDrawable *drawable, for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) + for (j = 0; j < width; j++, dh++, dv++, gr++) { - hmax = dh[j] - 128; - vmax = dv[j] - 128; - /* Find the gradient */ - gradient = sqrt (SQR (hmax) + SQR (vmax)); - if (!j || !i || (j == width - 1) || (i == height - 1)) - gr[j] = MAG_THRESHOLD; - else - gr[j] = (guchar) gradient; - } + *gr = MAG_THRESHOLD; + else { + hmax = *dh - 128; + vmax = *dv - 128; + + *gr = (guchar)sqrt (SQR (hmax) + SQR (hmax)); + } - dh += width; - dv += width; - gr += width; + } } } @@ -912,7 +909,7 @@ static void find_max_gradient (GPixelRgn *src_rgn, GPixelRgn *dest_rgn) { - guchar *s, *d; + guchar *s, *d, *s_iter, *s_end; gpointer pr; gint i, j; gint b; @@ -931,14 +928,25 @@ find_max_gradient (GPixelRgn *src_rgn, for (j = 0; j < src_rgn->w; j++) { max = 0; +#ifndef SLOW_CODE +#define ABSVAL(x) ((x) >= 0 ? (x) : -(x)) + + for(s_iter = s, s_end = s + src_rgn->bpp; + s_iter < s_end; s_iter++) { + val = *s; + if(ABSVAL(val) > ABSVAL(max)) + max = val; + } + *d++ = max; +#else for (b = 0; b < src_rgn->bpp; b++) { val = (gint) s[b] - 128; if (abs (val) > abs (max)) max = val; } - *d++ = (max + 128); +#endif s += src_rgn->bpp; } @@ -993,7 +1001,12 @@ gaussian_deriv (GPixelRgn *src_rgn, src = data; dest = data + length; +#ifdef UNOPTIMIZED_CODE length = 3; /* static for speed */ +#else + /* badhack :) */ +# define length 3 +#endif /* initialize */ curve = curve_array + length; @@ -1188,6 +1201,10 @@ gaussian_deriv (GPixelRgn *src_rgn, free (buf); free (data); +#ifndef UNOPTIMIZED_CODE + /* end bad hack */ +#undef length +#endif } /* @@ -2105,8 +2122,8 @@ fill_poly_color (Polygon *poly, gint min_x, min_y; gint max_x, max_y; gint size_x, size_y; - gint * max_scanlines; - gint * min_scanlines; + gint * max_scanlines, *max_scanlines_iter; + gint * min_scanlines, *min_scanlines_iter; gint * vals; gint val; gint pixel; @@ -2118,6 +2135,8 @@ fill_poly_color (Polygon *poly, gint supersample; gint supersample2; gint x1, y1, x2, y2; + Vertex *pts_tmp; + const int poly_npts = poly->npts; /* Determine antialiasing */ if (mvals.antialiasing) @@ -2132,15 +2151,29 @@ fill_poly_color (Polygon *poly, gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); bytes = drawable->bpp; - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; - calc_spec_vec (vecs+i, xs, ys, xe, ye); - } + /* begin loop */ + if(poly_npts) { + pts_tmp = poly->pts; + xs = (gint) pts_tmp[poly_npts-1].x; + ys = (gint) pts_tmp[poly_npts-1].y; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + calc_spec_vec (vecs, xs, ys, xe, ye); + + for (i = 1; i < poly_npts; i++) + { + xs = (gint) (pts_tmp->x); + ys = (gint) (pts_tmp->y); + pts_tmp++; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + calc_spec_vec (vecs+i, xs, ys, xe, ye); + } + } + /* end loop */ polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y); min_x = (gint) dmin_x; @@ -2151,43 +2184,62 @@ fill_poly_color (Polygon *poly, size_y = (max_y - min_y) * supersample; size_x = (max_x - min_x) * supersample; - min_scanlines = (gint *) malloc (sizeof (gint) * size_y); - max_scanlines = (gint *) malloc (sizeof (gint) * size_y); + min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); + max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); for (i = 0; i < size_y; i++) { min_scanlines[i] = max_x * supersample; max_scanlines[i] = min_x * supersample; } - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; + /* begin loop */ + if(poly_npts) { + pts_tmp = poly->pts; + xs = (gint) pts_tmp[poly_npts-1].x; + ys = (gint) pts_tmp[poly_npts-1].y; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; - xs *= supersample; - ys *= supersample; - xe *= supersample; - ye *= supersample; + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; - convert_segment (xs, ys, xe, ye, min_y * supersample, - min_scanlines, max_scanlines); - } + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + + for (i = 1; i < poly_npts; i++) + { + xs = (gint) pts_tmp->x; + ys = (gint) pts_tmp->y; + pts_tmp++; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; + + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + } + } + /* end loop */ gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, TRUE); vals = (gint *) malloc (sizeof (gint) * size_x); - for (i = 0; i < size_y; i++) + for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++) { if (! (i % supersample)) memset (vals, 0, sizeof (gint) * size_x); yy = (gdouble) i / (gdouble) supersample + min_y; - for (j = min_scanlines[i]; j < max_scanlines[i]; j++) + for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++) { x = j - min_x * supersample; vals[x] += 255; @@ -2212,15 +2264,13 @@ fill_poly_color (Polygon *poly, if (val > 0) { + xx = (gdouble) j / (gdouble) supersample + min_x; - contrib = calc_spec_contrib (vecs, poly->npts, xx, yy); + contrib = calc_spec_contrib (vecs, poly_npts, xx, yy); for (b = 0; b < bytes; b++) { - if (contrib < 0.0) - pixel = col[b] + (gint) ((col[b] - back[b]) * contrib); - else - pixel = col[b] + (gint) ((fore[b] - col[b]) * contrib); + pixel = col[b] + (gint) (((contrib < 0.0)?(col[b] - back[b]):(fore[b] - col[b])) * contrib); buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255; } diff --git a/plug-ins/cubism/cubism.c b/plug-ins/cubism/cubism.c index 6ce1e59242..6e3a18c295 100644 --- a/plug-ins/cubism/cubism.c +++ b/plug-ins/cubism/cubism.c @@ -17,6 +17,7 @@ * * You can contact me at quartic@polloux.fciencias.unam.mx * You can contact the original The Gimp authors at gimp@xcf.berkeley.edu + * Speedups by Elliot Lee */ @@ -96,7 +97,7 @@ static void randomize_indices (gint count, static gdouble fp_rand (gdouble val); static gint int_rand (gint val); static gdouble calc_alpha_blend (gdouble * vec, - gdouble dist, + gdouble one_over_dist, gdouble x, gdouble y); static void polygon_add_point (Polygon * poly, @@ -501,6 +502,27 @@ render_cubism (GDrawable *drawable) free (random_indices); } +G_INLINE_FUNC gdouble +calc_alpha_blend (gdouble *vec, + gdouble one_over_dist, + gdouble x, + gdouble y) +{ + gdouble r; + + if (!one_over_dist) + return 1.0; + else + { + r = (vec[0] * x + vec[1] * y) * one_over_dist; + if (r < 0.2) + r = 0.2; + else if (r > 1.0) + r = 1.0; + } + return r; +} + static void fill_poly_color (Polygon *poly, GDrawable *drawable, @@ -514,22 +536,23 @@ fill_poly_color (Polygon *poly, gint min_x, min_y; gint max_x, max_y; gint size_x, size_y; - gint * max_scanlines; - gint * min_scanlines; - gint * vals; + gint * max_scanlines, *max_scanlines_iter, *max_scanlines_end; + gint * min_scanlines, *min_scanlines_iter, *min_scanlines_end; gint val; gint alpha; gint bytes; guchar buf[4]; - gint b, i, j, k, x, y; + gint i, j, x, y; gdouble sx, sy; gdouble ex, ey; gdouble xx, yy; gdouble vec[2]; - gdouble dist; + gdouble dist, one_over_dist; gint supersample; gint supersample2; gint x1, y1, x2, y2; + gint *vals, *vals_iter, *vals_end; + gint pixel_gen_on_next_pass = -1; sx = poly->pts[0].x; sy = poly->pts[0].y; @@ -539,9 +562,11 @@ fill_poly_color (Polygon *poly, dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); if (dist > 0.0) { - vec[0] = (ex - sx) / dist; - vec[1] = (ey - sy) / dist; - } + one_over_dist = 1/dist; + vec[0] = (ex - sx) * one_over_dist; + vec[1] = (ey - sy) * one_over_dist; + } else + one_over_dist = 0.0; supersample = SUPERSAMPLE; supersample2 = SQR (supersample); @@ -558,20 +583,37 @@ fill_poly_color (Polygon *poly, size_y = (max_y - min_y) * supersample; size_x = (max_x - min_x) * supersample; - min_scanlines = (gint *) malloc (sizeof (gint) * size_y); - max_scanlines = (gint *) malloc (sizeof (gint) * size_y); + min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); + max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); for (i = 0; i < size_y; i++) { min_scanlines[i] = max_x * supersample; max_scanlines[i] = min_x * supersample; } - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; + if(poly->npts) { + gint poly_npts = poly->npts; + Vertex *curptr; + + xs = (gint) (poly->pts[poly_npts-1].x); + ys = (gint) (poly->pts[poly_npts-1].y); + xe = (gint) poly->pts[0].x; + ye = (gint) poly->pts[0].y; + + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; + + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + + for(i = 1, curptr = &poly->pts[0]; i < poly_npts; i++) { + xs = (gint) curptr->x; + ys = (gint) curptr->y; + curptr++; + xe = (gint) curptr->x; + ye = (gint) curptr->y; xs *= supersample; ys *= supersample; @@ -581,20 +623,22 @@ fill_poly_color (Polygon *poly, convert_segment (xs, ys, xe, ye, min_y * supersample, min_scanlines, max_scanlines); } + } gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, TRUE); vals = (gint *) malloc (sizeof (gint) * size_x); - for (i = 0; i < size_y; i++) + for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++) { - if (! (i % supersample)) + if (! (i % supersample)) { memset (vals, 0, sizeof (gint) * size_x); + } - yy = (gdouble) i / (gdouble) supersample + min_y; + yy = (gdouble)i / (gdouble)supersample + min_y; - for (j = min_scanlines[i]; j < max_scanlines[i]; j++) + for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++) { x = j - min_x * supersample; vals[x] += 255; @@ -612,21 +656,37 @@ fill_poly_color (Polygon *poly, if (x >= x1 && x < x2) { - val = 0; - for (k = 0; k < supersample; k++) - val += vals[j + k]; + for (val = 0, vals_iter = &vals[j], + vals_end = &vals_iter[supersample]; + vals_iter < vals_end; + vals_iter++) + val += *vals_iter; + val /= supersample2; if (val > 0) { xx = (gdouble) j / (gdouble) supersample + min_x; - alpha = (gint) (val * calc_alpha_blend (vec, dist, xx - sx, yy - sy)); + alpha = (gint) (val * calc_alpha_blend (vec, one_over_dist, xx - sx, yy - sy)); gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y); +#ifndef USE_READABLE_BUT_SLOW_CODE + { + guchar *buf_iter = buf, + *col_iter = col, + *buf_end = buf+bytes; + + for(; buf_iter < buf_end; buf_iter++, col_iter++) + *buf_iter = ((guint)(*col_iter * alpha) + + (((guint)*buf_iter) + * (256 - alpha))) >> 8; + } +#else /* original, pre-ECL code */ for (b = 0; b < bytes; b++) buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255; +#endif gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y); } } @@ -673,27 +733,6 @@ convert_segment (gint x1, } } -static gdouble -calc_alpha_blend (gdouble *vec, - gdouble dist, - gdouble x, - gdouble y) -{ - gdouble r; - - if (!dist) - return 1.0; - else - { - r = (vec[1] * y + vec[0] * x) / dist; - if (r < 0.2) - r = 0.2; - else if (r > 1.0) - r = 1.0; - } - return r; -} - static void randomize_indices (gint count, gint *indices) diff --git a/plug-ins/mosaic/mosaic.c b/plug-ins/mosaic/mosaic.c index b42a184e32..6a505b6477 100644 --- a/plug-ins/mosaic/mosaic.c +++ b/plug-ins/mosaic/mosaic.c @@ -20,6 +20,7 @@ * what appears to be a mosaic, composed of small primitives, * each of constant color and of an approximate size. * Copyright (C) 1996 Spencer Kimball + * Speedups by Elliot Lee */ #include @@ -887,23 +888,19 @@ find_gradients (GDrawable *drawable, for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) + for (j = 0; j < width; j++, dh++, dv++, gr++) { - hmax = dh[j] - 128; - vmax = dv[j] - 128; - /* Find the gradient */ - gradient = sqrt (SQR (hmax) + SQR (vmax)); - if (!j || !i || (j == width - 1) || (i == height - 1)) - gr[j] = MAG_THRESHOLD; - else - gr[j] = (guchar) gradient; - } + *gr = MAG_THRESHOLD; + else { + hmax = *dh - 128; + vmax = *dv - 128; + + *gr = (guchar)sqrt (SQR (hmax) + SQR (hmax)); + } - dh += width; - dv += width; - gr += width; + } } } @@ -912,7 +909,7 @@ static void find_max_gradient (GPixelRgn *src_rgn, GPixelRgn *dest_rgn) { - guchar *s, *d; + guchar *s, *d, *s_iter, *s_end; gpointer pr; gint i, j; gint b; @@ -931,14 +928,25 @@ find_max_gradient (GPixelRgn *src_rgn, for (j = 0; j < src_rgn->w; j++) { max = 0; +#ifndef SLOW_CODE +#define ABSVAL(x) ((x) >= 0 ? (x) : -(x)) + + for(s_iter = s, s_end = s + src_rgn->bpp; + s_iter < s_end; s_iter++) { + val = *s; + if(ABSVAL(val) > ABSVAL(max)) + max = val; + } + *d++ = max; +#else for (b = 0; b < src_rgn->bpp; b++) { val = (gint) s[b] - 128; if (abs (val) > abs (max)) max = val; } - *d++ = (max + 128); +#endif s += src_rgn->bpp; } @@ -993,7 +1001,12 @@ gaussian_deriv (GPixelRgn *src_rgn, src = data; dest = data + length; +#ifdef UNOPTIMIZED_CODE length = 3; /* static for speed */ +#else + /* badhack :) */ +# define length 3 +#endif /* initialize */ curve = curve_array + length; @@ -1188,6 +1201,10 @@ gaussian_deriv (GPixelRgn *src_rgn, free (buf); free (data); +#ifndef UNOPTIMIZED_CODE + /* end bad hack */ +#undef length +#endif } /* @@ -2105,8 +2122,8 @@ fill_poly_color (Polygon *poly, gint min_x, min_y; gint max_x, max_y; gint size_x, size_y; - gint * max_scanlines; - gint * min_scanlines; + gint * max_scanlines, *max_scanlines_iter; + gint * min_scanlines, *min_scanlines_iter; gint * vals; gint val; gint pixel; @@ -2118,6 +2135,8 @@ fill_poly_color (Polygon *poly, gint supersample; gint supersample2; gint x1, y1, x2, y2; + Vertex *pts_tmp; + const int poly_npts = poly->npts; /* Determine antialiasing */ if (mvals.antialiasing) @@ -2132,15 +2151,29 @@ fill_poly_color (Polygon *poly, gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); bytes = drawable->bpp; - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; - calc_spec_vec (vecs+i, xs, ys, xe, ye); - } + /* begin loop */ + if(poly_npts) { + pts_tmp = poly->pts; + xs = (gint) pts_tmp[poly_npts-1].x; + ys = (gint) pts_tmp[poly_npts-1].y; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + calc_spec_vec (vecs, xs, ys, xe, ye); + + for (i = 1; i < poly_npts; i++) + { + xs = (gint) (pts_tmp->x); + ys = (gint) (pts_tmp->y); + pts_tmp++; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + calc_spec_vec (vecs+i, xs, ys, xe, ye); + } + } + /* end loop */ polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y); min_x = (gint) dmin_x; @@ -2151,43 +2184,62 @@ fill_poly_color (Polygon *poly, size_y = (max_y - min_y) * supersample; size_x = (max_x - min_x) * supersample; - min_scanlines = (gint *) malloc (sizeof (gint) * size_y); - max_scanlines = (gint *) malloc (sizeof (gint) * size_y); + min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); + max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y); for (i = 0; i < size_y; i++) { min_scanlines[i] = max_x * supersample; max_scanlines[i] = min_x * supersample; } - for (i = 0; i < poly->npts; i++) - { - xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); - ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); - xe = (gint) poly->pts[i].x; - ye = (gint) poly->pts[i].y; + /* begin loop */ + if(poly_npts) { + pts_tmp = poly->pts; + xs = (gint) pts_tmp[poly_npts-1].x; + ys = (gint) pts_tmp[poly_npts-1].y; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; - xs *= supersample; - ys *= supersample; - xe *= supersample; - ye *= supersample; + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; - convert_segment (xs, ys, xe, ye, min_y * supersample, - min_scanlines, max_scanlines); - } + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + + for (i = 1; i < poly_npts; i++) + { + xs = (gint) pts_tmp->x; + ys = (gint) pts_tmp->y; + pts_tmp++; + xe = (gint) pts_tmp->x; + ye = (gint) pts_tmp->y; + + xs *= supersample; + ys *= supersample; + xe *= supersample; + ye *= supersample; + + convert_segment (xs, ys, xe, ye, min_y * supersample, + min_scanlines, max_scanlines); + } + } + /* end loop */ gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, TRUE); vals = (gint *) malloc (sizeof (gint) * size_x); - for (i = 0; i < size_y; i++) + for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++) { if (! (i % supersample)) memset (vals, 0, sizeof (gint) * size_x); yy = (gdouble) i / (gdouble) supersample + min_y; - for (j = min_scanlines[i]; j < max_scanlines[i]; j++) + for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++) { x = j - min_x * supersample; vals[x] += 255; @@ -2212,15 +2264,13 @@ fill_poly_color (Polygon *poly, if (val > 0) { + xx = (gdouble) j / (gdouble) supersample + min_x; - contrib = calc_spec_contrib (vecs, poly->npts, xx, yy); + contrib = calc_spec_contrib (vecs, poly_npts, xx, yy); for (b = 0; b < bytes; b++) { - if (contrib < 0.0) - pixel = col[b] + (gint) ((col[b] - back[b]) * contrib); - else - pixel = col[b] + (gint) ((fore[b] - col[b]) * contrib); + pixel = col[b] + (gint) (((contrib < 0.0)?(col[b] - back[b]):(fore[b] - col[b])) * contrib); buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255; }