diff options
author | Carl Worth <cworth@cworth.org> | 2006-01-04 17:59:03 +0000 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2006-01-04 17:59:03 +0000 |
commit | 9737b4de39162a86844e07f50aa76e881063dab9 (patch) | |
tree | e9a50e05d93242fa9b12dc641fd8854d1d521fd4 | |
parent | 19441311e471b661b6b2a6854f030aafa7715d5d (diff) |
2005-10-10 David Reveman <davidr@novell.com>
Throw away old gradient code from within cairo-pattern.c in favor of using new support in pixman for gradients.
Update reference images for all tests involving gradients since the gradient output has changed slightly.
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 14 | ||||
-rw-r--r-- | src/cairo-matrix.c | 17 | ||||
-rw-r--r-- | src/cairo-pattern.c | 594 | ||||
-rw-r--r-- | src/cairoint.h | 29 | ||||
-rw-r--r-- | test/clip-operator-ref.png | bin | 37134 -> 36956 bytes | |||
-rw-r--r-- | test/clip-operator-rgb24-ref.png | bin | 21014 -> 20991 bytes | |||
-rw-r--r-- | test/gradient-alpha-ref.png | bin | 154 -> 155 bytes | |||
-rw-r--r-- | test/gradient-alpha-rgb24-ref.png | bin | 147 -> 152 bytes | |||
-rw-r--r-- | test/linear-gradient-ref.png | bin | 12719 -> 12750 bytes | |||
-rw-r--r-- | test/linear-gradient-rgb24-ref.png | bin | 12719 -> 11700 bytes | |||
-rw-r--r-- | test/mask-ref.png | bin | 87846 -> 87837 bytes | |||
-rw-r--r-- | test/mask-rgb24-ref.png | bin | 73124 -> 73292 bytes | |||
-rw-r--r-- | test/operator-clear-ref.png | bin | 4971 -> 4933 bytes | |||
-rw-r--r-- | test/operator-clear-rgb24-ref.png | bin | 5704 -> 5677 bytes | |||
-rw-r--r-- | test/operator-source-ref.png | bin | 19982 -> 19684 bytes | |||
-rw-r--r-- | test/operator-source-rgb24-ref.png | bin | 16909 -> 16746 bytes | |||
-rw-r--r-- | test/text-pattern-ref.png | bin | 2731 -> 2725 bytes | |||
-rw-r--r-- | test/text-pattern-rgb24-ref.png | bin | 2686 -> 2704 bytes | |||
-rw-r--r-- | test/trap-clip-ref.png | bin | 71701 -> 71785 bytes | |||
-rw-r--r-- | test/trap-clip-rgb24-ref.png | bin | 64724 -> 64728 bytes | |||
-rw-r--r-- | test/unbounded-operator-ref.png | bin | 11994 -> 11964 bytes | |||
-rw-r--r-- | test/unbounded-operator-rgb24-ref.png | bin | 7581 -> 7555 bytes |
23 files changed, 221 insertions, 473 deletions
@@ -1,3 +1,43 @@ +2006-01-04 Carl Worth <cworth@cworth.org> + + * Originally: 2005-10-10 David Reveman <davidr@novell.com> + + * src/cairoint.h: + * src/cairo-image-surface.c: (_cairo_image_surface_set_matrix): + * src/cairo-matrix.c: (_cairo_matrix_to_pixman_matrix): + * src/cairo-pattern.c: (_cairo_gradient_pattern_init_copy), + (_cairo_pattern_init_linear), (_cairo_pattern_init_radial), + (_cairo_pattern_add_color_stop), + (cairo_pattern_add_color_stop_rgb), + (cairo_pattern_add_color_stop_rgba), + (_cairo_linear_pattern_classify), + (_cairo_pattern_acquire_surface_for_gradient), + (_cairo_pattern_acquire_surface): + + Throw away old gradient code from within cairo-pattern.c in favor + of using new support in pixman for gradients. + + * test/clip-operator-ref.png: + * test/clip-operator-rgb24-ref.png: + * test/gradient-alpha-ref.png: + * test/gradient-alpha-rgb24-ref.png: + * test/linear-gradient-ref.png: + * test/linear-gradient-rgb24-ref.png: + * test/mask-ref.png: + * test/mask-rgb24-ref.png: + * test/operator-clear-ref.png: + * test/operator-clear-rgb24-ref.png: + * test/operator-source-ref.png: + * test/operator-source-rgb24-ref.png: + * test/text-pattern-ref.png: + * test/text-pattern-rgb24-ref.png: + * test/trap-clip-ref.png: + * test/trap-clip-rgb24-ref.png: + * test/unbounded-operator-ref.png: + * test/unbounded-operator-rgb24-ref.png: Update reference images + for all tests involving gradients since the gradient output has + changed slightly. + 2006-01-03 Vladimir Vukicevic <vladimir@pobox.com> * src/cairo-glitz-surface.c (_cairo_glitz_surface_create_similar): diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 9aabade4..329590d1 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -51,7 +51,7 @@ _cairo_format_bpp (cairo_format_t format) } } -static cairo_surface_t * +cairo_surface_t * _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, cairo_format_t format) { @@ -476,17 +476,7 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface, { pixman_transform_t pixman_transform; - pixman_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx); - pixman_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy); - pixman_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0); - - pixman_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx); - pixman_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy); - pixman_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0); - - pixman_transform.matrix[2][0] = 0; - pixman_transform.matrix[2][1] = 0; - pixman_transform.matrix[2][2] = _cairo_fixed_from_double (1); + _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform); pixman_image_set_transform (surface->pixman_image, &pixman_transform); diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index d75fc210..83e297ac 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -700,3 +700,20 @@ _cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radi * double min = radius * sqrt (f - sqrt (g*g+h*h)); */ } + +void +_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, + pixman_transform_t *pixman_transform) +{ + pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx); + pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy); + pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0); + + pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx); + pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy); + pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0); + + pixman_transform->matrix[2][0] = 0; + pixman_transform->matrix[2][1] = 0; + pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1); +} diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 5c2505dc..d7b73693 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -29,23 +29,6 @@ #include "cairoint.h" -typedef struct _cairo_shader_color_stop { - cairo_fixed_t offset; - cairo_fixed_48_16_t scale; - int id; - unsigned char color_char[4]; -} cairo_shader_color_stop_t; - -typedef struct _cairo_shader_op { - cairo_shader_color_stop_t *stops; - int n_stops; - cairo_extend_t extend; -} cairo_shader_op_t; - -#define MULTIPLY_COLORCOMP(c1, c2) \ - ((unsigned char) \ - ((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff)) - const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_SOLID, /* type */ (unsigned int)-1, /* ref_count */ @@ -165,14 +148,15 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, if (other->n_stops) { - pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t)); + pattern->stops = malloc (other->n_stops * + sizeof (pixman_gradient_stop_t)); if (pattern->stops == NULL) { _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); return; } memcpy (pattern->stops, other->stops, - other->n_stops * sizeof (cairo_color_stop_t)); + other->n_stops * sizeof (pixman_gradient_stop_t)); } } @@ -273,11 +257,11 @@ _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern, double x0, double y0, double x1, double y1) { _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_LINEAR); - - pattern->point0.x = x0; - pattern->point0.y = y0; - pattern->point1.x = x1; - pattern->point1.y = y1; + + pattern->gradient.p1.x = _cairo_fixed_from_double (x0); + pattern->gradient.p1.y = _cairo_fixed_from_double (y0); + pattern->gradient.p2.x = _cairo_fixed_from_double (x1); + pattern->gradient.p2.y = _cairo_fixed_from_double (y1); } void @@ -287,12 +271,12 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, { _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_RADIAL); - pattern->center0.x = cx0; - pattern->center0.y = cy0; - pattern->radius0 = fabs (radius0); - pattern->center1.x = cx1; - pattern->center1.y = cy1; - pattern->radius1 = fabs (radius1); + pattern->gradient.inner.x = _cairo_fixed_from_double (cx0); + pattern->gradient.inner.y = _cairo_fixed_from_double (cy0); + pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0)); + pattern->gradient.outer.x = _cairo_fixed_from_double (cx1); + pattern->gradient.outer.y = _cairo_fixed_from_double (cy1); + pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1)); } cairo_pattern_t * @@ -586,25 +570,45 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) static void _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, double offset, - cairo_color_t *color) + double red, + double green, + double blue, + double alpha) { - cairo_color_stop_t *stop; - cairo_color_stop_t *new_stops; + pixman_gradient_stop_t *new_stops; + cairo_fixed_t x; + int i; - pattern->n_stops++; - new_stops = realloc (pattern->stops, - pattern->n_stops * sizeof (cairo_color_stop_t)); - if (new_stops == NULL) { + new_stops = realloc (pattern->stops, (pattern->n_stops + 1) * + sizeof (pixman_gradient_stop_t)); + if (new_stops == NULL) + { _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); return; } - + pattern->stops = new_stops; - stop = &pattern->stops[pattern->n_stops - 1]; + x = _cairo_fixed_from_double (offset); + for (i = 0; i < pattern->n_stops; i++) + { + if (x < new_stops[i].x) + { + memmove (&new_stops[i + 1], &new_stops[i], + sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i)); + + break; + } + } + + new_stops[i].x = x; - stop->offset = _cairo_fixed_from_double (offset); - stop->color = *color; + new_stops[i].color.red = red * 65535.0; + new_stops[i].color.green = green * 65535.0; + new_stops[i].color.blue = blue * 65535.0; + new_stops[i].color.alpha = alpha * 65535.0; + + pattern->n_stops++; } /** @@ -634,8 +638,6 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, double green, double blue) { - cairo_color_t color; - if (pattern->status) return; @@ -651,10 +653,8 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, _cairo_restrict_value (&green, 0.0, 1.0); _cairo_restrict_value (&blue, 0.0, 1.0); - _cairo_color_init_rgb (&color, red, green, blue); _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, - offset, - &color); + offset, red, green, blue, 1.0); } /** @@ -686,8 +686,6 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, double blue, double alpha) { - cairo_color_t color; - if (pattern->status) return; @@ -704,10 +702,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, _cairo_restrict_value (&blue, 0.0, 1.0); _cairo_restrict_value (&alpha, 0.0, 1.0); - _cairo_color_init_rgba (&color, red, green, blue, alpha); _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, - offset, - &color); + offset, red, green, blue, alpha); } /** @@ -824,231 +820,6 @@ _cairo_pattern_transform (cairo_pattern_t *pattern, cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix); } -#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \ - (((c2 * factor) + (c1 * (65536 - factor))) / 65536) - -static void -_cairo_pattern_shader_linear (unsigned char *color0, - unsigned char *color1, - cairo_fixed_t factor, - uint32_t *pixel) -{ - *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) | - (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) | - (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) | - (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0)); -} - -#undef INTERPOLATE_COLOR_LINEAR - -static int -_cairo_shader_color_stop_compare (const void *elem1, const void *elem2) -{ - cairo_shader_color_stop_t *s1 = (cairo_shader_color_stop_t *) elem1; - cairo_shader_color_stop_t *s2 = (cairo_shader_color_stop_t *) elem2; - - return - (s1->offset == s2->offset) ? - /* equal offsets, sort on id */ - ((s1->id < s2->id) ? -1 : 1) : - /* sort on offset */ - ((s1->offset < s2->offset) ? -1 : 1); -} - -static cairo_status_t -_cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern, - cairo_shader_op_t *op) -{ - int i; - - op->stops = malloc (pattern->n_stops * sizeof (cairo_shader_color_stop_t)); - if (!op->stops) - return CAIRO_STATUS_NO_MEMORY; - - for (i = 0; i < pattern->n_stops; i++) - { - op->stops[i].color_char[0] = pattern->stops[i].color.red * 0xff; - op->stops[i].color_char[1] = pattern->stops[i].color.green * 0xff; - op->stops[i].color_char[2] = pattern->stops[i].color.blue * 0xff; - op->stops[i].color_char[3] = pattern->stops[i].color.alpha * 0xff; - op->stops[i].offset = pattern->stops[i].offset; - op->stops[i].id = i; - } - - /* sort stops in ascending order */ - qsort (op->stops, pattern->n_stops, sizeof (cairo_shader_color_stop_t), - _cairo_shader_color_stop_compare); - - /* this scale value is used only when computing gradient values - * before the defined range, in which case stop 0 is used for both - * ends of the interpolation, making the value of 'scale' not - * actually matter, except that valgrind notices we're using - * an undefined value. - */ - op->stops[0].scale = 0; - for (i = 0; i < pattern->n_stops - 1; i++) - { - op->stops[i + 1].scale = op->stops[i + 1].offset - op->stops[i].offset; - if (op->stops[i + 1].scale == 65536) - op->stops[i + 1].scale = 0; - } - - op->n_stops = pattern->n_stops; - op->extend = pattern->base.extend; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_pattern_shader_fini (cairo_shader_op_t *op) -{ - if (op->stops) - free (op->stops); -} - -/* Find two color stops bounding the given offset. If the given offset - * is before the first or after the last stop offset, the nearest - * offset is returned twice. - */ -static void -_cairo_shader_op_find_color_stops (cairo_shader_op_t *op, - cairo_fixed_t offset, - cairo_shader_color_stop_t *stops[2]) -{ - int i; - - /* Before first stop. */ - if (offset <= op->stops[0].offset) { - stops[0] = &op->stops[0]; - stops[1] = &op->stops[0]; - return; - } - - /* Between two stops. */ - for (i = 0; i < op->n_stops - 1; i++) { - if (offset <= op->stops[i + 1].offset) { - stops[0] = &op->stops[i]; - stops[1] = &op->stops[i + 1]; - return; - } - } - - /* After last stop. */ - stops[0] = &op->stops[op->n_stops - 1]; - stops[1] = &op->stops[op->n_stops - 1]; -} - -static void -_cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op, - cairo_fixed_t factor, - uint32_t *pixel) -{ - cairo_shader_color_stop_t *stops[2]; - - switch (op->extend) { - case CAIRO_EXTEND_REPEAT: - factor -= factor & 0xffff0000; - break; - case CAIRO_EXTEND_REFLECT: - if (factor < 0 || factor > 65536) { - if ((factor >> 16) % 2) - factor = 65536 - (factor - (factor & 0xffff0000)); - else - factor -= factor & 0xffff0000; - } - break; - case CAIRO_EXTEND_PAD: - case CAIRO_EXTEND_NONE: - break; - } - - _cairo_shader_op_find_color_stops (op, factor, stops); - - /* take offset as new 0 of coordinate system */ - factor -= stops[0]->offset; - - /* difference between two offsets == 0, abrubt change */ - if (stops[1]->scale) - factor = ((cairo_fixed_48_16_t) factor << 16) / - stops[1]->scale; - - _cairo_pattern_shader_linear (stops[0]->color_char, - stops[1]->color_char, - factor, pixel); - - /* multiply alpha */ - if (((unsigned char) (*pixel >> 24)) != 0xff) { - *pixel = (*pixel & 0xff000000) | - (MULTIPLY_COLORCOMP (*pixel >> 16, *pixel >> 24) << 16) | - (MULTIPLY_COLORCOMP (*pixel >> 8, *pixel >> 24) << 8) | - (MULTIPLY_COLORCOMP (*pixel >> 0, *pixel >> 24) << 0); - } -} - -static cairo_status_t -_cairo_image_data_set_linear (cairo_linear_pattern_t *pattern, - double offset_x, - double offset_y, - uint32_t *pixels, - int width, - int height) -{ - int x, y; - cairo_point_double_t point0, point1; - double a, b, c, d, tx, ty; - double scale, start, dx, dy, factor; - cairo_shader_op_t op; - cairo_status_t status; - - status = _cairo_pattern_shader_init (&pattern->base, &op); - if (status) - return status; - - /* We compute the position in the linear gradient for - * a point q as: - * - * [q . (p1 - p0) - p0 . (p1 - p0)] / (p1 - p0) ^ 2 - * - * The computation is done in pattern space. The - * calculation could be heavily optimized by using the - * fact that 'factor' increases linearly in both - * directions. - */ - point0.x = pattern->point0.x; - point0.y = pattern->point0.y; - point1.x = pattern->point1.x; - point1.y = pattern->point1.y; - - _cairo_matrix_get_affine (&pattern->base.base.matrix, - &a, &b, &c, &d, &tx, &ty); - - dx = point1.x - point0.x; - dy = point1.y - point0.y; - scale = dx * dx + dy * dy; - scale = (scale) ? 1.0 / scale : 1.0; - - start = dx * point0.x + dy * point0.y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - double qx_device = x + offset_x; - double qy_device = y + offset_y; - - /* transform fragment into pattern space */ - double qx = a * qx_device + c * qy_device + tx; - double qy = b * qx_device + d * qy_device + ty; - - factor = ((dx * qx + dy * qy) - start) * scale; - - _cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++); - } - } - - _cairo_pattern_shader_fini (&op); - - return CAIRO_STATUS_SUCCESS; -} - static void _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern, double offset_x, @@ -1069,10 +840,10 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern, * pattern. We actually only need 3/4 corners, so we skip the * fourth. */ - point0.x = pattern->point0.x; - point0.y = pattern->point0.y; - point1.x = pattern->point1.x; - point1.y = pattern->point1.y; + point0.x = _cairo_fixed_to_double (pattern->gradient.p1.x); + point0.y = _cairo_fixed_to_double (pattern->gradient.p1.y); + point1.x = _cairo_fixed_to_double (pattern->gradient.p2.x); + point1.y = _cairo_fixed_to_double (pattern->gradient.p2.y); _cairo_matrix_get_affine (&pattern->base.base.matrix, &a, &b, &c, &d, &tx, &ty); @@ -1107,131 +878,6 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern, *is_horizontal = factors[2] == factors[0]; } -static cairo_status_t -_cairo_image_data_set_radial (cairo_radial_pattern_t *pattern, - double offset_x, - double offset_y, - uint32_t *pixels, - int width, - int height) -{ - int x, y, aligned_circles; - cairo_point_double_t c0, c1; - double px, py, ex, ey; - double a, b, c, d, tx, ty; - double r0, r1, c0_e_x, c0_e_y, c0_e, c1_e_x, c1_e_y, c1_e, - c0_c1_x, c0_c1_y, c0_c1, angle_c0, c1_y, y_x, c0_y, c0_x, r1_2, - denumerator, fraction, factor; - cairo_shader_op_t op; - cairo_status_t status; - - status = _cairo_pattern_shader_init (&pattern->base, &op); - if (status) - return status; - - c0.x = pattern->center0.x; - c0.y = pattern->center0.y; - r0 = pattern->radius0; - c1.x = pattern->center1.x; - c1.y = pattern->center1.y; - r1 = pattern->radius1; - - if (c0.x != c1.x || c0.y != c1.y) { - aligned_circles = 0; - c0_c1_x = c1.x - c0.x; - c0_c1_y = c1.y - c0.y; - c0_c1 = sqrt (c0_c1_x * c0_c1_x + c0_c1_y * c0_c1_y); - r1_2 = r1 * r1; - } else { - aligned_circles = 1; - r1 = 1.0 / (r1 - r0); - r1_2 = c0_c1 = 0.0; /* shut up compiler */ - } - - _cairo_matrix_get_affine (&pattern->base.base.matrix, - &a, &b, &c, &d, &tx, &ty); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - px = x + offset_x; - py = y + offset_y; - - /* transform fragment */ - ex = a * px + c * py + tx; - ey = b * px + d * py + ty; - - if (aligned_circles) { - ex = ex - c1.x; - ey = ey - c1.y; - - factor = (sqrt (ex * ex + ey * ey) - r0) * r1; - } else { - /* - y (ex, ey) - c0 -------------------+---------- x - \ | __-- - \ | __-- - \ | __-- - \ | __-- r1 - \ | __-- - c1 -- - - We need to calulate distance c0->x; the distance from - the inner circle center c0, through fragment position - (ex, ey) to point x where it crosses the outer circle. - - From points c0, c1 and (ex, ey) we get angle C0. With - angle C0 we calculate distance c1->y and c0->y and by - knowing c1->y and r1, we also know y->x. Adding y->x to - c0->y gives us c0->x. The gradient offset can then be - calculated as: - - offset = (c0->e - r0) / (c0->x - r0) - - */ - - c0_e_x = ex - c0.x; - c0_e_y = ey - c0.y; - c0_e = sqrt (c0_e_x * c0_e_x + c0_e_y * c0_e_y); - - c1_e_x = ex - c1.x; - c1_e_y = ey - c1.y; - c1_e = sqrt (c1_e_x * c1_e_x + c1_e_y * c1_e_y); - - denumerator = -2.0 * c0_e * c0_c1; - - if (denumerator != 0.0) { - fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) / - denumerator; - - if (fraction > 1.0) - fraction = 1.0; - else if (fraction < -1.0) - fraction = -1.0; - - angle_c0 = acos (fraction); - - c0_y = cos (angle_c0) * c0_c1; - c1_y = sin (angle_c0) * c0_c1; - - y_x = sqrt (r1_2 - c1_y * c1_y); - c0_x = y_x + c0_y; - - factor = (c0_e - r0) / (c0_x - r0); - } else { - factor = -r0; - } - } - - _cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++); - } - } - - _cairo_pattern_shader_fini (&op); - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, cairo_surface_t *dst, @@ -1243,9 +889,52 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, cairo_surface_attributes_t *attr) { cairo_image_surface_t *image; - cairo_status_t status; - uint32_t *data; - cairo_bool_t repeat = FALSE; + pixman_image_t *pixman_image; + pixman_transform_t pixman_transform; + cairo_status_t status; + cairo_bool_t repeat = FALSE; + + if (pattern->base.type == CAIRO_PATTERN_LINEAR) + { + cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; + + pixman_image = pixman_image_create_linear_gradient (&linear->gradient, + pattern->stops, + pattern->n_stops); + } + else + { + cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; + + pixman_image = pixman_image_create_radial_gradient (&radial->gradient, + pattern->stops, + pattern->n_stops); + } + + if (pixman_image == NULL) + return CAIRO_STATUS_NO_MEMORY; + + if (_cairo_surface_is_image (dst)) + { + image = (cairo_image_surface_t *) + _cairo_image_surface_create_for_pixman_image (pixman_image, + CAIRO_FORMAT_ARGB32); + if (image->base.status) + { + pixman_image_destroy (pixman_image); + return CAIRO_STATUS_NO_MEMORY; + } + + attr->x_offset = attr->y_offset = 0; + attr->matrix = pattern->base.matrix; + attr->extend = pattern->base.extend; + attr->filter = CAIRO_FILTER_NEAREST; + attr->acquired = FALSE; + + *out = &image->base; + + return CAIRO_STATUS_SUCCESS; + } if (pattern->base.type == CAIRO_PATTERN_LINEAR) { cairo_bool_t is_horizontal; @@ -1270,46 +959,47 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, repeat = TRUE; } } - - data = malloc (width * height * 4); - if (data == NULL) - return CAIRO_STATUS_NO_MEMORY; - - if (pattern->base.type == CAIRO_PATTERN_LINEAR) - { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern; - - status = _cairo_image_data_set_linear (linear, x, y, data, - width, height); - } - else - { - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern; - - status = _cairo_image_data_set_radial (radial, x, y, data, - width, height); - } - - if (status) { - free (data); - return status; - } image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data ((unsigned char *) data, - CAIRO_FORMAT_ARGB32, - width, height, - width * 4); - + cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); if (image->base.status) { - free (data); + pixman_image_destroy (pixman_image); return CAIRO_STATUS_NO_MEMORY; } - _cairo_image_surface_assume_ownership_of_data (image); - + pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR); + + _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform); + pixman_image_set_transform (pixman_image, &pixman_transform); + + switch (pattern->base.extend) { + case CAIRO_EXTEND_NONE: + pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE); + break; + case CAIRO_EXTEND_REPEAT: + pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL); + break; + case CAIRO_EXTEND_REFLECT: + pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT); + break; + case CAIRO_EXTEND_PAD: + pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD); + break; + } + + pixman_composite (PIXMAN_OPERATOR_SRC, + pixman_image, + NULL, + image->pixman_image, + x, y, + 0, 0, + 0, 0, + width, height); + + pixman_image_destroy (pixman_image); + status = _cairo_surface_clone_similar (dst, &image->base, out); - + cairo_surface_destroy (&image->base); attr->x_offset = -x; @@ -1318,7 +1008,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE; attr->filter = CAIRO_FILTER_NEAREST; attr->acquired = FALSE; - + return status; } @@ -1476,15 +1166,27 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, /* fast path for gradients with less than 2 color stops */ if (src->n_stops < 2) { - const cairo_color_t *color; cairo_solid_pattern_t solid; if (src->n_stops) - color = &src->stops->color; + { + cairo_color_t color; + + _cairo_color_init_rgba (&color, + src->stops->color.red / 65536.0, + src->stops->color.green / 65536.0, + src->stops->color.blue / 65536.0, + src->stops->color.alpha / 65536.0); + + _cairo_pattern_init_solid (&solid, &color); + } else - color = CAIRO_COLOR_TRANSPARENT; + { + const cairo_color_t *color; - _cairo_pattern_init_solid (&solid, color); + color = _cairo_stock_color (CAIRO_STOCK_TRANSPARENT); + _cairo_pattern_init_solid (&solid, color); + } status = _cairo_pattern_acquire_surface_for_solid (&solid, dst, x, y, diff --git a/src/cairoint.h b/src/cairoint.h index 9ebedd9f..dfcc36ce 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -916,11 +916,6 @@ typedef enum { CAIRO_PATTERN_RADIAL } cairo_pattern_type_t; -typedef struct _cairo_color_stop { - cairo_fixed_t offset; - cairo_color_t color; -} cairo_color_stop_t; - struct _cairo_pattern { cairo_pattern_type_t type; unsigned int ref_count; @@ -946,24 +941,20 @@ typedef struct _cairo_surface_pattern { typedef struct _cairo_gradient_pattern { cairo_pattern_t base; - cairo_color_stop_t *stops; - int n_stops; + pixman_gradient_stop_t *stops; + int n_stops; } cairo_gradient_pattern_t; typedef struct _cairo_linear_pattern { cairo_gradient_pattern_t base; - - cairo_point_double_t point0; - cairo_point_double_t point1; + + pixman_linear_gradient_t gradient; } cairo_linear_pattern_t; typedef struct _cairo_radial_pattern { cairo_gradient_pattern_t base; - - cairo_point_double_t center0; - cairo_point_double_t center1; - double radius0; - double radius1; + + pixman_radial_gradient_t gradient; } cairo_radial_pattern_t; typedef union { @@ -1827,6 +1818,10 @@ _cairo_format_from_content (cairo_content_t content); cairo_private cairo_content_t _cairo_content_from_format (cairo_format_t format); +cairo_surface_t * +_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, + cairo_format_t format); + cairo_private cairo_surface_t * _cairo_image_surface_create_with_masks (unsigned char *data, cairo_format_masks_t *format, @@ -1944,6 +1939,10 @@ _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix, cairo_private double _cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius); +cairo_private void +_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, + pixman_transform_t *pixman_transform); + /* cairo_traps.c */ cairo_private void _cairo_traps_init (cairo_traps_t *traps); diff --git a/test/clip-operator-ref.png b/test/clip-operator-ref.png Binary files differindex d81a7341..cc8d8327 100644 --- a/test/clip-operator-ref.png +++ b/test/clip-operator-ref.png diff --git a/test/clip-operator-rgb24-ref.png b/test/clip-operator-rgb24-ref.png Binary files differindex 1d3c03a4..9d6d686a 100644 --- a/test/clip-operator-rgb24-ref.png +++ b/test/clip-operator-rgb24-ref.png diff --git a/test/gradient-alpha-ref.png b/test/gradient-alpha-ref.png Binary files differindex 11f19ac5..7acbb3b0 100644 --- a/test/gradient-alpha-ref.png +++ b/test/gradient-alpha-ref.png diff --git a/test/gradient-alpha-rgb24-ref.png b/test/gradient-alpha-rgb24-ref.png Binary files differindex 23aeae0c..383bfb05 100644 --- a/test/gradient-alpha-rgb24-ref.png +++ b/test/gradient-alpha-rgb24-ref.png diff --git a/test/linear-gradient-ref.png b/test/linear-gradient-ref.png Binary files differindex 454ed1f2..64ceddf8 100644 --- a/test/linear-gradient-ref.png +++ b/test/linear-gradient-ref.png diff --git a/test/linear-gradient-rgb24-ref.png b/test/linear-gradient-rgb24-ref.png Binary files differindex 454ed1f2..9cc54584 100644 --- a/test/linear-gradient-rgb24-ref.png +++ b/test/linear-gradient-rgb24-ref.png diff --git a/test/mask-ref.png b/test/mask-ref.png Binary files differindex 4b357c0a..d28e6423 100644 --- a/test/mask-ref.png +++ b/test/mask-ref.png diff --git a/test/mask-rgb24-ref.png b/test/mask-rgb24-ref.png Binary files differindex 0148c6a6..e3b7724c 100644 --- a/test/mask-rgb24-ref.png +++ b/test/mask-rgb24-ref.png diff --git a/test/operator-clear-ref.png b/test/operator-clear-ref.png Binary files differindex 73082afd..ff7afb4d 100644 --- a/test/operator-clear-ref.png +++ b/test/operator-clear-ref.png diff --git a/test/operator-clear-rgb24-ref.png b/test/operator-clear-rgb24-ref.png Binary files differindex d528f19e..a125abe6 100644 --- a/test/operator-clear-rgb24-ref.png +++ b/test/operator-clear-rgb24-ref.png diff --git a/test/operator-source-ref.png b/test/operator-source-ref.png Binary files differindex ab7d263c..5cd35716 100644 --- a/test/operator-source-ref.png +++ b/test/operator-source-ref.png diff --git a/test/operator-source-rgb24-ref.png b/test/operator-source-rgb24-ref.png Binary files differindex 594fc7b7..18f1bae5 100644 --- a/test/operator-source-rgb24-ref.png +++ b/test/operator-source-rgb24-ref.png diff --git a/test/text-pattern-ref.png b/test/text-pattern-ref.png Binary files differindex a6290dfe..8f8fc79a 100644 --- a/test/text-pattern-ref.png +++ b/test/text-pattern-ref.png diff --git a/test/text-pattern-rgb24-ref.png b/test/text-pattern-rgb24-ref.png Binary files differindex 9ef43dda..d7304857 100644 --- a/test/text-pattern-rgb24-ref.png +++ b/test/text-pattern-rgb24-ref.png diff --git a/test/trap-clip-ref.png b/test/trap-clip-ref.png Binary files differindex 9b5b317a..d7397a92 100644 --- a/test/trap-clip-ref.png +++ b/test/trap-clip-ref.png diff --git a/test/trap-clip-rgb24-ref.png b/test/trap-clip-rgb24-ref.png Binary files differindex b1958b08..0fea43b0 100644 --- a/test/trap-clip-rgb24-ref.png +++ b/test/trap-clip-rgb24-ref.png diff --git a/test/unbounded-operator-ref.png b/test/unbounded-operator-ref.png Binary files differindex fa344692..231019d8 100644 --- a/test/unbounded-operator-ref.png +++ b/test/unbounded-operator-ref.png diff --git a/test/unbounded-operator-rgb24-ref.png b/test/unbounded-operator-rgb24-ref.png Binary files differindex 23677563..1321dd00 100644 --- a/test/unbounded-operator-rgb24-ref.png +++ b/test/unbounded-operator-rgb24-ref.png |