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