summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-06-19 18:57:45 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-06-20 04:45:20 -0400
commit3074d57b560d5ec9be2a0e1a6846012698f51208 (patch)
tree3dc2395cd45731d3fd3492cfcc50840b4ee55f1d
parent66365b5ef1bb85863669227ae6e31134d8d57013 (diff)
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 (a) make sure the given angle is between 0 and 360, and (b) add or subtract 2 * M_PI if the computed angle ends up outside [0, 2 * pi]. 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.
-rw-r--r--pixman/pixman-conical-gradient.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index 1c8ddba..d06dd0b 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -32,6 +32,24 @@
#include <math.h>
#include "pixman-private.h"
+static force_inline double
+coordinates_to_parameter (double x, double y, double angle)
+{
+ double t;
+
+ t = atan2 (y, x) + angle;
+
+ while (t < 0)
+ t += 2 * M_PI;
+
+ while (t >= 2 * M_PI)
+ t -= 2 * M_PI;
+
+ return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
+ * make rotation CCW
+ */
+}
+
static void
conical_gradient_get_scanline_32 (pixman_image_t *image,
int x,
@@ -52,7 +70,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
double rx = x + 0.5;
double ry = y + 0.5;
double rz = 1.;
- double a = (conical->angle * M_PI) / (180. * 65536);
+ double a = pixman_fixed_to_double ((conical->angle * M_PI) / 180.0);
_pixman_gradient_walker_init (&walker, gradient, source->common.repeat);
@@ -71,11 +89,11 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
cx = source->common.transform->matrix[0][0] / 65536.;
cy = source->common.transform->matrix[1][0] / 65536.;
cz = source->common.transform->matrix[2][0] / 65536.;
-
+
rx = v.vector[0] / 65536.;
ry = v.vector[1] / 65536.;
rz = v.vector[2] / 65536.;
-
+
affine =
source->common.transform->matrix[2][0] == 0 &&
v.vector[2] == pixman_fixed_1;
@@ -88,20 +106,16 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
while (buffer < end)
{
- double angle;
-
if (!mask || *mask++)
{
- pixman_fixed_48_16_t t;
-
- angle = atan2 (ry, rx) + a;
- t = (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));
+ double t = coordinates_to_parameter (rx, ry, a);
- *buffer = _pixman_gradient_walker_pixel (&walker, t);
+ *buffer = _pixman_gradient_walker_pixel (
+ &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
}
++buffer;
-
+
rx += cx;
ry += cy;
}
@@ -111,11 +125,10 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
while (buffer < end)
{
double x, y;
- double angle;
if (!mask || *mask++)
{
- pixman_fixed_48_16_t t;
+ double t;
if (rz != 0)
{
@@ -129,15 +142,15 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
x -= conical->center.x / 65536.;
y -= conical->center.y / 65536.;
-
- angle = atan2 (y, x) + a;
- t = (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));
- *buffer = _pixman_gradient_walker_pixel (&walker, t);
+ t = coordinates_to_parameter (x, y, a);
+
+ *buffer = _pixman_gradient_walker_pixel (
+ &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
}
++buffer;
-
+
rx += cx;
ry += cy;
rz += cz;
@@ -174,7 +187,7 @@ pixman_image_create_conical_gradient (pixman_point_fixed_t * center,
image->type = CONICAL;
conical->center = *center;
- conical->angle = angle;
+ conical->angle = MOD (angle, 360 << 16);
image->common.property_changed = conical_gradient_property_changed;