diff options
author | Andrea Canciani <ranma42@gmail.com> | 2010-11-16 14:44:10 +0100 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2010-12-13 17:22:37 +0100 |
commit | cb2bac969f006b0ed3fedd22e475a97ba8559e91 (patch) | |
tree | 02972740665aa3d473cc940d8c3233014c7d845a | |
parent | eae2f47bc2338a3c6727e2021aca71fde9132f4d (diff) |
float gradient
-rw-r--r-- | pixman/pixman-conical-gradient.c | 34 | ||||
-rw-r--r-- | pixman/pixman-gradient-walker.c | 9 | ||||
-rw-r--r-- | pixman/pixman-image.c | 20 | ||||
-rw-r--r-- | pixman/pixman-linear-gradient.c | 44 | ||||
-rw-r--r-- | pixman/pixman-private.h | 13 | ||||
-rw-r--r-- | pixman/pixman-radial-gradient.c | 81 |
6 files changed, 126 insertions, 75 deletions
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c index 2bd3ec7..3bb283d 100644 --- a/pixman/pixman-conical-gradient.c +++ b/pixman/pixman-conical-gradient.c @@ -52,16 +52,15 @@ coordinates_to_parameter (double x, double y, double angle) } static void -conical_gradient_get_scanline_32 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) +conical_gradient_get_scanline (pixman_image_t *image, + int x, + int y, + int width, + pixman_component_t * buffer, + const pixman_component_t *mask) { gradient_t *gradient = (gradient_t *)image; conical_gradient_t *conical = (conical_gradient_t *)image; - uint32_t *end = buffer + width; pixman_gradient_walker_t walker; pixman_bool_t affine = TRUE; double cx = 1.; @@ -103,17 +102,18 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, rx -= conical->center.x / 65536.; ry -= conical->center.y / 65536.; - while (buffer < end) + while (width--) { if (!mask || *mask++) { double t = coordinates_to_parameter (rx, ry, conical->angle); - *buffer = _pixman_gradient_walker_pixel ( - &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); + _pixman_gradient_walker_pixel (&walker, + (pixman_fixed_48_16_t)pixman_double_to_fixed (t), + buffer); } - ++buffer; + buffer += 4; rx += cx; ry += cy; @@ -121,7 +121,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, } else { - while (buffer < end) + while (width--) { double x, y; @@ -144,11 +144,12 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, t = coordinates_to_parameter (x, y, conical->angle); - *buffer = _pixman_gradient_walker_pixel ( - &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t)); + _pixman_gradient_walker_pixel (&walker, + (pixman_fixed_48_16_t)pixman_double_to_fixed (t), + buffer); } - ++buffer; + buffer += 4; rx += cx; ry += cy; @@ -160,8 +161,9 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, static void conical_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_32 = conical_gradient_get_scanline_32; + image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32; image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; + image->common.get_scanline = conical_gradient_get_scanline; } PIXMAN_EXPORT pixman_image_t * diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c index 5598a9d..13cd298 100644 --- a/pixman/pixman-gradient-walker.c +++ b/pixman/pixman-gradient-walker.c @@ -221,9 +221,10 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, /* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */ -uint32_t +void _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t x) + pixman_fixed_32_32_t x, + pixman_component_t *buffer) { int dist, idist; uint32_t t1, t2, a, color; @@ -250,6 +251,8 @@ _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, t2 = (t2 >> 8) * a + 0x800080; t2 = (t2 + ((t2 >> 8) & 0xff00ff)); - return (color | (t1 & 0xff00ff) | (t2 & 0xff00)); + color |= (t1 & 0xff00ff) | (t2 & 0xff00); + + pixman_expand_to_float (buffer, &color, PIXMAN_a8r8g8b8, 1); } diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index bc91542..2054a2d 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -88,6 +88,26 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t * image, free (mask8); } +/* + * By default, just evaluate the image at 32bpp and expand. Individual image + * types can plug in a better scanline getter if they want to. For example + * we could produce smoother gradients by evaluating them at higher color + * depth, but that's a project for the future. + */ +void +_pixman_image_get_scanline_gradient_32 (pixman_image_t * image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t * mask) +{ + pixman_component_t *tmp = pixman_malloc_abc (width, 4, sizeof(pixman_component_t)); + image->common.get_scanline (image, x, y, width, tmp, NULL); + pixman_contract_from_float (buffer, tmp, width); + free (tmp); +} + pixman_image_t * _pixman_image_allocate (void) { diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c index 1547882..3a1812d 100644 --- a/pixman/pixman-linear-gradient.c +++ b/pixman/pixman-linear-gradient.c @@ -92,19 +92,18 @@ linear_gradient_classify (pixman_image_t *image, } static void -linear_gradient_get_scanline_32 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) +linear_gradient_get_scanline (pixman_image_t *image, + int x, + int y, + int width, + pixman_component_t * buffer, + const pixman_component_t *mask) { pixman_vector_t v, unit; pixman_fixed_32_32_t l; pixman_fixed_48_16_t dx, dy; gradient_t *gradient = (gradient_t *)image; linear_gradient_t *linear = (linear_gradient_t *)image; - uint32_t *end = buffer + width; pixman_gradient_walker_t walker; _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); @@ -161,27 +160,33 @@ linear_gradient_get_scanline_32 (pixman_image_t *image, if (((pixman_fixed_32_32_t )(inc * width)) == 0) { - register uint32_t color; + pixman_component_t color[4]; - color = _pixman_gradient_walker_pixel (&walker, t); - while (buffer < end) - *buffer++ = color; + _pixman_gradient_walker_pixel (&walker, t, color); + while (width--) + { + *buffer++ = color[0]; + *buffer++ = color[1]; + *buffer++ = color[2]; + *buffer++ = color[3]; + } } else { int i; i = 0; - while (buffer < end) + while (width--) { if (!mask || *mask++) { - *buffer = _pixman_gradient_walker_pixel (&walker, - t + next_inc); + _pixman_gradient_walker_pixel (&walker, + t + next_inc, + buffer); } i++; next_inc = inc * i; - buffer++; + buffer+=4; } } } @@ -192,7 +197,7 @@ linear_gradient_get_scanline_32 (pixman_image_t *image, t = 0; - while (buffer < end) + while (width--) { if (!mask || *mask++) { @@ -207,10 +212,10 @@ linear_gradient_get_scanline_32 (pixman_image_t *image, (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden; } - *buffer = _pixman_gradient_walker_pixel (&walker, t); + _pixman_gradient_walker_pixel (&walker, t, buffer); } - ++buffer; + buffer += 4; v.vector[0] += unit.vector[0]; v.vector[1] += unit.vector[1]; @@ -222,8 +227,9 @@ linear_gradient_get_scanline_32 (pixman_image_t *image, static void linear_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_32 = linear_gradient_get_scanline_32; + image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32; image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; + image->common.get_scanline = linear_gradient_get_scanline; } PIXMAN_EXPORT pixman_image_t * diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 4580cae..8225225 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -215,6 +215,14 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t *image, uint32_t * buffer, const uint32_t *mask); +void +_pixman_image_get_scanline_gradient_32 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask); + source_image_class_t _pixman_image_classify (pixman_image_t *image, int x, @@ -337,9 +345,10 @@ void _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker, pixman_fixed_32_32_t pos); -uint32_t +void _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker, - pixman_fixed_32_32_t x); + pixman_fixed_32_32_t x, + pixman_component_t *buffer); /* * Edges diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c index b595ba7..62d26fc 100644 --- a/pixman/pixman-radial-gradient.c +++ b/pixman/pixman-radial-gradient.c @@ -66,7 +66,7 @@ fdot (double x1, return x1 * x2 + y1 * y2 + z1 * z2; } -static uint32_t +static void radial_compute_color (double a, double b, double c, @@ -74,7 +74,8 @@ radial_compute_color (double a, double dr, double mindr, pixman_gradient_walker_t *walker, - pixman_repeat_t repeat) + pixman_repeat_t repeat, + pixman_component_t *buffer) { /* * In this function error propagation can lead to bad results: @@ -96,8 +97,10 @@ radial_compute_color (double a, if (a == 0) { - return _pixman_gradient_walker_pixel (walker, - pixman_fixed_1 / 2 * c / b); + _pixman_gradient_walker_pixel (walker, + pixman_fixed_1 / 2 * c / b, + buffer); + return; } det = fdot (b, a, 0, b, -c, 0); @@ -112,29 +115,35 @@ radial_compute_color (double a, if (repeat == PIXMAN_REPEAT_NONE) { if (0 <= t0 && t0 <= pixman_fixed_1) - return _pixman_gradient_walker_pixel (walker, t0); + _pixman_gradient_walker_pixel (walker, t0, buffer); else if (0 <= t1 && t1 <= pixman_fixed_1) - return _pixman_gradient_walker_pixel (walker, t1); + _pixman_gradient_walker_pixel (walker, t1, buffer); + else + memset (buffer, 0, sizeof (pixman_component_t) * 4); } else { if (t0 * dr > mindr) - return _pixman_gradient_walker_pixel (walker, t0); + _pixman_gradient_walker_pixel (walker, t0, buffer); else if (t1 * dr > mindr) - return _pixman_gradient_walker_pixel (walker, t1); + _pixman_gradient_walker_pixel (walker, t1, buffer); + else + memset (buffer, 0, sizeof (pixman_component_t) * 4); } } - - return 0; + else + { + memset (buffer, 0, sizeof (pixman_component_t) * 4); + } } static void -radial_gradient_get_scanline_32 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) +radial_gradient_get_scanline (pixman_image_t *image, + int x, + int y, + int width, + pixman_component_t * buffer, + const pixman_component_t *mask) { /* * Implementation of radial gradients following the PDF specification. @@ -220,7 +229,6 @@ radial_gradient_get_scanline_32 (pixman_image_t *image, gradient_t *gradient = (gradient_t *)image; radial_gradient_t *radial = (radial_gradient_t *)image; - uint32_t *end = buffer + width; pixman_gradient_walker_t walker; pixman_vector_t v, unit; @@ -299,22 +307,23 @@ radial_gradient_get_scanline_32 (pixman_image_t *image, ddc = 2 * dot (unit.vector[0], unit.vector[1], 0, unit.vector[0], unit.vector[1], 0); - while (buffer < end) + while (width--) { if (!mask || *mask++) { - *buffer = radial_compute_color (radial->a, b, c, - radial->inva, - radial->delta.radius, - radial->mindr, - &walker, - image->common.repeat); + radial_compute_color (radial->a, b, c, + radial->inva, + radial->delta.radius, + radial->mindr, + &walker, + image->common.repeat, + buffer); } b += db; c += dc; dc += ddc; - ++buffer; + buffer += 4; } } else @@ -323,7 +332,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image, /* Warning: * error propagation guarantees are much looser than in the affine case */ - while (buffer < end) + while (width--) { if (!mask || *mask++) { @@ -348,20 +357,21 @@ radial_gradient_get_scanline_32 (pixman_image_t *image, pdx, pdy, radial->c1.radius); /* / pixman_fixed_1 / pixman_fixed_1 */ - *buffer = radial_compute_color (radial->a, b, c, - radial->inva, - radial->delta.radius, - radial->mindr, - &walker, - image->common.repeat); + radial_compute_color (radial->a, b, c, + radial->inva, + radial->delta.radius, + radial->mindr, + &walker, + image->common.repeat, + buffer); } else { - *buffer = 0; + memset (buffer, 0, sizeof (pixman_component_t) * 4); } } - ++buffer; + buffer += 4; v.vector[0] += unit.vector[0]; v.vector[1] += unit.vector[1]; @@ -373,8 +383,9 @@ radial_gradient_get_scanline_32 (pixman_image_t *image, static void radial_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_32 = radial_gradient_get_scanline_32; + image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32; image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; + image->common.get_scanline = radial_gradient_get_scanline; } PIXMAN_EXPORT pixman_image_t * |