diff options
-rw-r--r-- | pixman/pixman-gradient-walker.c | 99 | ||||
-rw-r--r-- | pixman/pixman-image.c | 73 |
2 files changed, 88 insertions, 84 deletions
diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c index 53d0b30..3848247 100644 --- a/pixman/pixman-gradient-walker.c +++ b/pixman/pixman-gradient-walker.c @@ -56,8 +56,6 @@ gradient_walker_reset (pixman_gradient_walker_t *walker, int n, count = walker->num_stops; pixman_gradient_stop_t *stops = walker->stops; - static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; - switch (walker->repeat) { case PIXMAN_REPEAT_NORMAL: @@ -68,27 +66,12 @@ gradient_walker_reset (pixman_gradient_walker_t *walker, break; } - if (n == 0) - { - left_x = stops[count - 1].x - 0x10000; - left_c = &stops[count - 1].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } + left_x = stops[n - 1].x; + left_c = &stops[n - 1].color; + + right_x = stops[n].x; + right_c = &stops[n].color; - if (n == count) - { - right_x = stops[0].x + 0x10000; - right_c = &stops[0].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } left_x += (pos - x); right_x += (pos - x); break; @@ -100,27 +83,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker, break; } - if (n == 0) - { - left_x = INT32_MIN; - left_c = &stops[0].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } + left_x = stops[n - 1].x; + left_c = &stops[n - 1].color; - if (n == count) - { - right_x = INT32_MAX; - right_c = &stops[n - 1].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } + right_x = stops[n].x; + right_c = &stops[n].color; break; case PIXMAN_REPEAT_REFLECT: @@ -134,27 +101,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker, break; } - if (n == 0) - { - left_x = -stops[0].x; - left_c = &stops[0].color; - } - else - { - left_x = stops[n - 1].x; - left_c = &stops[n - 1].color; - } + left_x = stops[n - 1].x; + left_c = &stops[n - 1].color; - if (n == count) - { - right_x = 0x20000 - stops[n - 1].x; - right_c = &stops[n - 1].color; - } - else - { - right_x = stops[n].x; - right_c = &stops[n].color; - } + right_x = stops[n].x; + right_c = &stops[n].color; if ((int32_t)pos & 0x10000) { @@ -182,25 +133,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker, break; } - if (n == 0) - { - left_x = INT32_MIN; - right_x = stops[0].x; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else if (n == count) - { - left_x = stops[n - 1].x; - right_x = INT32_MAX; - left_c = right_c = (pixman_color_t*) &transparent_black; - } - else - { - left_x = stops[n - 1].x; - right_x = stops[n].x; - left_c = &stops[n - 1].color; - right_c = &stops[n].color; - } + left_x = stops[n - 1].x; + left_c = &stops[n - 1].color; + + right_x = stops[n].x; + right_c = &stops[n].color; } walker->left_x = left_x; diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index afe587f..09d7cbc 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -31,6 +31,50 @@ #include "pixman-private.h" +static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; + +static void +gradient_property_changed (pixman_image_t *image) +{ + gradient_t *gradient = &image->gradient; + int n = gradient->n_stops; + pixman_gradient_stop_t *stops = gradient->stops; + pixman_gradient_stop_t *begin = &(gradient->stops[-1]); + pixman_gradient_stop_t *end = &(gradient->stops[n]); + + switch (gradient->common.repeat) + { + default: + case PIXMAN_REPEAT_NONE: + begin->x = INT32_MIN; + begin->color = transparent_black; + end->x = INT32_MAX; + end->color = transparent_black; + break; + + case PIXMAN_REPEAT_NORMAL: + begin->x = stops[n - 1].x - pixman_fixed_1; + begin->color = stops[n - 1].color; + end->x = stops[0].x + pixman_fixed_1; + end->color = stops[0].color; + break; + + case PIXMAN_REPEAT_REFLECT: + begin->x = - stops[0].x; + begin->color = stops[0].color; + end->x = pixman_int_to_fixed (2) - stops[n - 1].x; + end->color = stops[n - 1].color; + break; + + case PIXMAN_REPEAT_PAD: + begin->x = INT32_MIN; + begin->color = stops[0].color; + end->x = INT32_MAX; + end->color = stops[n - 1].color; + break; + } +} + pixman_bool_t _pixman_init_gradient (gradient_t * gradient, const pixman_gradient_stop_t *stops, @@ -38,14 +82,27 @@ _pixman_init_gradient (gradient_t * gradient, { return_val_if_fail (n_stops > 0, FALSE); - gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t)); + /* We allocate two extra stops, one before the beginning of the stop list, + * and one after the end. These stops are initialized to whatever color + * would be used for positions outside the range of the stop list. + * + * This saves a bit of computation in the gradient walker. + * + * The pointer we store in the gradient_t struct still points to the + * first user-supplied struct, so when freeing, we will have to + * subtract one. + */ + gradient->stops = + pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t)); if (!gradient->stops) return FALSE; + gradient->stops += 1; memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t)); - gradient->n_stops = n_stops; + gradient->common.property_changed = gradient_property_changed; + return TRUE; } @@ -102,7 +159,17 @@ _pixman_image_fini (pixman_image_t *image) image->type == CONICAL) { if (image->gradient.stops) - free (image->gradient.stops); + { + /* See _pixman_init_gradient() for an explanation of the - 1 */ + free (image->gradient.stops - 1); + } + + /* This will trigger if someone adds a property_changed + * method to the linear/radial/conical gradient overwriting + * the general one. + */ + assert ( + image->common.property_changed == gradient_property_changed); } if (image->type == BITS && image->bits.free_me) |