diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-03-26 18:31:58 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-03-26 18:31:58 -0400 |
commit | c36a619145a3d18cdc2686fbe8e22f3d5376d7b8 (patch) | |
tree | a93a8628f42e80d69d9378e5a9f4c66e1d64725a | |
parent | 57c9cb83267b5baeaaf46ac7c2c3b8ba728c0092 (diff) |
Add completely untested fast path for radial gradientsradial-fast
-rw-r--r-- | pixman/pixman-fast-path.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index bf5b298c..b6d0159d 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -28,6 +28,7 @@ #endif #include <string.h> #include <stdlib.h> +#include <math.h> #include "pixman-private.h" #include "pixman-combine32.h" @@ -1748,6 +1749,108 @@ fast_composite_scaled_nearest (pixman_implementation_t *imp, } } +static void +fast_composite_over_radial_8_8888 (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + pixman_gradient_walker_t walker; + gradient_t *gradient = &(src_image->gradient); + uint32_t * dst_line, *dst; + uint8_t * mask_line, *mask; + int dst_stride; + int mask_stride; + uint32_t w; + radial_gradient_t *radial = (radial_gradient_t *)src_image; + int i, j; + + double cx = 1.; + double cy = 0.; + + PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, + dst_stride, dst_line, 1); + PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint8_t, + mask_stride, mask_line, 1); + + _pixman_gradient_walker_init (&walker, gradient, src_image->common.repeat); + + double r1 = radial->c1.radius / 65536.; + double r1sq = r1 * r1; + double A = radial->A; + double invA = -65536. / (2. * A); + double A4 = -4. * A; + pixman_bool_t invert = A * radial->dr < 0; + + for (j = dest_y; j < dest_y + height; ++j) + { + dst = dst_line; + dst_line += dst_stride; + mask = mask_line; + mask_line += mask_stride; + w = width; + double ry = j + 0.5; + double rx = dest_x + 0.5; + double pdx = rx - radial->c1.x / 65536.; + double pdy = ry - radial->c1.y / 65536.; + double B = -2. * (pdx*radial->cdx + pdy*radial->cdy + r1*radial->dr); + double cB = -2. * (cx*radial->cdx + cy*radial->cdy); + + for (i = dest_x; i < dest_x + width; ++i) + { + uint32_t m = *mask; + + if (m) + { + pixman_fixed_48_16_t t; + uint32_t s, sa, d; + double det = B * B + A4 * (pdx * pdx + pdy * pdy - r1sq); + if (det <= 0.) + t = (pixman_fixed_48_16_t) (B * invA); + else if (invert) + t = (pixman_fixed_48_16_t) ((B + sqrt (det)) * invA); + else + t = (pixman_fixed_48_16_t) ((B - sqrt (det)) * invA); + + s = _pixman_gradient_walker_pixel (&walker, t); + + UN8x4_MUL_UN8 (s, m); + + sa = s >> 24; + + if (sa == 0xff) + { + *dst = s; + } + else + { + d = *dst; + sa = ~sa; + + UN8x4_MUL_UN8_ADD_UN8x4 (d, sa, s); + + *dst = d; + } + } + + pdx += cx; + pdy += cy; + B += cB; + dst++; + mask++; + } + } +} + static const pixman_fast_path_t c_fast_paths[] = { PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565), @@ -1878,6 +1981,15 @@ static const pixman_fast_path_t c_fast_paths[] = NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8), NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8), + { PIXMAN_OP_OVER, + PIXMAN_radial, ( FAST_PATH_ID_TRANSFORM | + FAST_PATH_NO_ACCESSORS | + FAST_PATH_NO_WIDE_FORMAT), + PIXMAN_a8, ( _FAST_PATH_STANDARD_FLAGS ), + PIXMAN_a8r8g8b8, ( FAST_PATH_STD_DEST_FLAGS ), + fast_composite_over_radial_8_8888 + }, + { PIXMAN_OP_NONE }, }; |