No subject

=3D?UTF-8?q?S=3DC3=3DB8ren=3D20Sandmann=3D20Pedersen?=3D ssp at redhat.=
Sat Jun 19 16:12:47 PDT 2010


com>
Date: Sat, 19 Jun 2010 18:57:45 -0400
Subject: [PATCH] Fix conical gradients to match QConicalGradient from Qt

Under the assumption that pixman gradients are supposed to match
QConicalgradient, described here:

        http://doc.trolltech.com/4.4/qconicalgradient.html

this patch fixes two separate bugs in pixman-conical-gradient.c.

The first bug is that the output of atan2() is in the range of [-pi,
pi], which means the parameter into the gradient can be negative. This
is wrong since a QConicalGradient always interpolates around the
center from 0 to 1. The fix for that is to simply to add 2*pi to the
parameter, and then use fmod() to make sure we didn't end up outside
the [0, 2*pi] range.

The other bug is that we were interpolating clockwise, whereas
QConicalGradient calls for a counter-clockwise interpolation. This is
easily fixed by subtracting the parameter from 1.

Finally, this patch encapsulates the computation in a new force-inline
function so that it can be reused in both the affine and non-affine
case.
---
 pixman/pixman-conical-gradient.c |   35 +++++++++++++++++++++--------------
 1 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradi=
ent.c
index 1c8ddba..7d368dc 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -32,6 +32,18 @@
 #include <math.h>
 #include "pixman-private.h"
=20
+static force_inline double
+coordinates_to_parameter (double x, double y, double angle)
+{
+    double t;
+
+    t =3D atan2 (y, x) + 2 * M_PI;	/* Add 2 * M_PI to make it positive */
+    t +=3D angle;				/* Add the rotation */
+    t =3D fmod (t, 2 * M_PI);		/* Make sure t is within [0, 2 * pi] */
+
+    return 1 - t / (2 * M_PI);		/* Scale t to [0, 1] and make the rotation=
 CCW */
+}
+
 static void
 conical_gradient_get_scanline_32 (pixman_image_t *image,
                                   int             x,
@@ -52,7 +64,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
     double rx =3D x + 0.5;
     double ry =3D y + 0.5;
     double rz =3D 1.;
-    double a =3D (conical->angle * M_PI) / (180. * 65536);
+    double a =3D pixman_fixed_to_double ((conical->angle * M_PI) / 180.0);
=20
     _pixman_gradient_walker_init (&walker, gradient, source->common.repeat=
);
=20
@@ -88,16 +100,12 @@ conical_gradient_get_scanline_32 (pixman_image_t *imag=
e,
=20
 	while (buffer < end)
 	{
-	    double angle;
-
 	    if (!mask || *mask++)
 	    {
-		pixman_fixed_48_16_t t;
+		double t =3D coordinates_to_parameter (rx, ry, a);
=20
-		angle =3D atan2 (ry, rx) + a;
-		t     =3D (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));
-
-		*buffer =3D _pixman_gradient_walker_pixel (&walker, t);
+		*buffer =3D _pixman_gradient_walker_pixel (
+		    &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
 	    }
=20
 	    ++buffer;
@@ -111,11 +119,10 @@ conical_gradient_get_scanline_32 (pixman_image_t *ima=
ge,
 	while (buffer < end)
 	{
 	    double x, y;
-	    double angle;
=20
 	    if (!mask || *mask++)
 	    {
-		pixman_fixed_48_16_t t;
+		double t;
=20
 		if (rz !=3D 0)
 		{
@@ -129,11 +136,11 @@ conical_gradient_get_scanline_32 (pixman_image_t *ima=
ge,
=20
 		x -=3D conical->center.x / 65536.;
 		y -=3D conical->center.y / 65536.;
-=09=09
-		angle =3D atan2 (y, x) + a;
-		t     =3D (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));
=20
-		*buffer =3D _pixman_gradient_walker_pixel (&walker, t);
+		t =3D coordinates_to_parameter (x, y, a);
+
+		*buffer =3D _pixman_gradient_walker_pixel (
+		    &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
 	    }
=20
 	    ++buffer;
--=20
1.7.0.1


More information about the cairo mailing list