[cairo-commit] cairo/src cairo-image-surface.c, 1.68, 1.69 cairo-matrix.c, 1.34, 1.35 cairo-pattern.c, 1.70, 1.71 cairoint.h, 1.240, 1.241

Carl Worth commit at pdx.freedesktop.org
Wed Jan 4 17:59:05 PST 2006


Committed by: cworth

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv29415/src

Modified Files:
	cairo-image-surface.c cairo-matrix.c cairo-pattern.c 
	cairoint.h 
Log Message:

2006-01-04  Carl Worth  <cworth at cworth.org>

        * Originally: 2005-10-10  David Reveman  <davidr at 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.


Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- cairo-image-surface.c	3 Jan 2006 17:23:48 -0000	1.68
+++ cairo-image-surface.c	5 Jan 2006 01:59:03 -0000	1.69
@@ -51,7 +51,7 @@
     }
 }
 
-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 @@
 {
     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);
 

Index: cairo-matrix.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-matrix.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- cairo-matrix.c	12 Sep 2005 18:11:33 -0000	1.34
+++ cairo-matrix.c	5 Jan 2006 01:59:03 -0000	1.35
@@ -700,3 +700,20 @@
      * 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);
+}

Index: cairo-pattern.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pattern.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -d -r1.70 -r1.71
--- cairo-pattern.c	7 Nov 2005 21:23:32 -0000	1.70
+++ cairo-pattern.c	5 Jan 2006 01:59:03 -0000	1.71
@@ -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 @@
 
     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 @@
 			    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_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 @@
 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));
 
-    stop->offset = _cairo_fixed_from_double (offset);
-    stop->color = *color;
+	    break;
+	}
+    }
+
+    new_stops[i].x = x;
+
+    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 @@
 				  double	   green,
 				  double	   blue)
 {
-    cairo_color_t color;
-
     if (pattern->status)
 	return;
 
@@ -651,10 +653,8 @@
     _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 @@
 				   double	   blue,
 				   double	   alpha)
 {
-    cairo_color_t color;
-
     if (pattern->status)
 	return;
 
@@ -704,10 +702,8 @@
     _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_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 @@
      * 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 @@
     *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_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 @@
 	    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 @@
     attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
     attr->filter = CAIRO_FILTER_NEAREST;
     attr->acquired = FALSE;
-    
+
     return status;
 }
 
@@ -1476,15 +1166,27 @@
 	/* 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,

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.240
retrieving revision 1.241
diff -u -d -r1.240 -r1.241
--- cairoint.h	22 Dec 2005 00:35:33 -0000	1.240
+++ cairoint.h	5 Jan 2006 01:59:03 -0000	1.241
@@ -916,11 +916,6 @@
     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_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_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_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);



More information about the cairo-commit mailing list