summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Canciani <ranma42@gmail.com>2010-11-16 14:44:10 +0100
committerAndrea Canciani <ranma42@gmail.com>2010-12-13 17:22:37 +0100
commitcb2bac969f006b0ed3fedd22e475a97ba8559e91 (patch)
tree02972740665aa3d473cc940d8c3233014c7d845a
parenteae2f47bc2338a3c6727e2021aca71fde9132f4d (diff)
float gradient
-rw-r--r--pixman/pixman-conical-gradient.c34
-rw-r--r--pixman/pixman-gradient-walker.c9
-rw-r--r--pixman/pixman-image.c20
-rw-r--r--pixman/pixman-linear-gradient.c44
-rw-r--r--pixman/pixman-private.h13
-rw-r--r--pixman/pixman-radial-gradient.c81
6 files changed, 126 insertions, 75 deletions
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index 2bd3ec7..3bb283d 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -52,16 +52,15 @@ coordinates_to_parameter (double x, double y, double angle)
}
static void
-conical_gradient_get_scanline_32 (pixman_image_t *image,
- int x,
- int y,
- int width,
- uint32_t * buffer,
- const uint32_t *mask)
+conical_gradient_get_scanline (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ pixman_component_t * buffer,
+ const pixman_component_t *mask)
{
gradient_t *gradient = (gradient_t *)image;
conical_gradient_t *conical = (conical_gradient_t *)image;
- uint32_t *end = buffer + width;
pixman_gradient_walker_t walker;
pixman_bool_t affine = TRUE;
double cx = 1.;
@@ -103,17 +102,18 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
rx -= conical->center.x / 65536.;
ry -= conical->center.y / 65536.;
- while (buffer < end)
+ while (width--)
{
if (!mask || *mask++)
{
double t = coordinates_to_parameter (rx, ry, conical->angle);
- *buffer = _pixman_gradient_walker_pixel (
- &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
+ _pixman_gradient_walker_pixel (&walker,
+ (pixman_fixed_48_16_t)pixman_double_to_fixed (t),
+ buffer);
}
- ++buffer;
+ buffer += 4;
rx += cx;
ry += cy;
@@ -121,7 +121,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
}
else
{
- while (buffer < end)
+ while (width--)
{
double x, y;
@@ -144,11 +144,12 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
t = coordinates_to_parameter (x, y, conical->angle);
- *buffer = _pixman_gradient_walker_pixel (
- &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
+ _pixman_gradient_walker_pixel (&walker,
+ (pixman_fixed_48_16_t)pixman_double_to_fixed (t),
+ buffer);
}
- ++buffer;
+ buffer += 4;
rx += cx;
ry += cy;
@@ -160,8 +161,9 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
static void
conical_gradient_property_changed (pixman_image_t *image)
{
- image->common.get_scanline_32 = conical_gradient_get_scanline_32;
+ image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32;
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+ image->common.get_scanline = conical_gradient_get_scanline;
}
PIXMAN_EXPORT pixman_image_t *
diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index 5598a9d..13cd298 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -221,9 +221,10 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
-uint32_t
+void
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
- pixman_fixed_32_32_t x)
+ pixman_fixed_32_32_t x,
+ pixman_component_t *buffer)
{
int dist, idist;
uint32_t t1, t2, a, color;
@@ -250,6 +251,8 @@ _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
t2 = (t2 >> 8) * a + 0x800080;
t2 = (t2 + ((t2 >> 8) & 0xff00ff));
- return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
+ color |= (t1 & 0xff00ff) | (t2 & 0xff00);
+
+ pixman_expand_to_float (buffer, &color, PIXMAN_a8r8g8b8, 1);
}
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index bc91542..2054a2d 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -88,6 +88,26 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t * image,
free (mask8);
}
+/*
+ * By default, just evaluate the image at 32bpp and expand. Individual image
+ * types can plug in a better scanline getter if they want to. For example
+ * we could produce smoother gradients by evaluating them at higher color
+ * depth, but that's a project for the future.
+ */
+void
+_pixman_image_get_scanline_gradient_32 (pixman_image_t * image,
+ int x,
+ int y,
+ int width,
+ uint32_t * buffer,
+ const uint32_t * mask)
+{
+ pixman_component_t *tmp = pixman_malloc_abc (width, 4, sizeof(pixman_component_t));
+ image->common.get_scanline (image, x, y, width, tmp, NULL);
+ pixman_contract_from_float (buffer, tmp, width);
+ free (tmp);
+}
+
pixman_image_t *
_pixman_image_allocate (void)
{
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 1547882..3a1812d 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -92,19 +92,18 @@ linear_gradient_classify (pixman_image_t *image,
}
static void
-linear_gradient_get_scanline_32 (pixman_image_t *image,
- int x,
- int y,
- int width,
- uint32_t * buffer,
- const uint32_t *mask)
+linear_gradient_get_scanline (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ pixman_component_t * buffer,
+ const pixman_component_t *mask)
{
pixman_vector_t v, unit;
pixman_fixed_32_32_t l;
pixman_fixed_48_16_t dx, dy;
gradient_t *gradient = (gradient_t *)image;
linear_gradient_t *linear = (linear_gradient_t *)image;
- uint32_t *end = buffer + width;
pixman_gradient_walker_t walker;
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
@@ -161,27 +160,33 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
{
- register uint32_t color;
+ pixman_component_t color[4];
- color = _pixman_gradient_walker_pixel (&walker, t);
- while (buffer < end)
- *buffer++ = color;
+ _pixman_gradient_walker_pixel (&walker, t, color);
+ while (width--)
+ {
+ *buffer++ = color[0];
+ *buffer++ = color[1];
+ *buffer++ = color[2];
+ *buffer++ = color[3];
+ }
}
else
{
int i;
i = 0;
- while (buffer < end)
+ while (width--)
{
if (!mask || *mask++)
{
- *buffer = _pixman_gradient_walker_pixel (&walker,
- t + next_inc);
+ _pixman_gradient_walker_pixel (&walker,
+ t + next_inc,
+ buffer);
}
i++;
next_inc = inc * i;
- buffer++;
+ buffer+=4;
}
}
}
@@ -192,7 +197,7 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
t = 0;
- while (buffer < end)
+ while (width--)
{
if (!mask || *mask++)
{
@@ -207,10 +212,10 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
}
- *buffer = _pixman_gradient_walker_pixel (&walker, t);
+ _pixman_gradient_walker_pixel (&walker, t, buffer);
}
- ++buffer;
+ buffer += 4;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
@@ -222,8 +227,9 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
static void
linear_gradient_property_changed (pixman_image_t *image)
{
- image->common.get_scanline_32 = linear_gradient_get_scanline_32;
+ image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32;
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+ image->common.get_scanline = linear_gradient_get_scanline;
}
PIXMAN_EXPORT pixman_image_t *
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 4580cae..8225225 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -215,6 +215,14 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t *image,
uint32_t * buffer,
const uint32_t *mask);
+void
+_pixman_image_get_scanline_gradient_32 (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask);
+
source_image_class_t
_pixman_image_classify (pixman_image_t *image,
int x,
@@ -337,9 +345,10 @@ void
_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
pixman_fixed_32_32_t pos);
-uint32_t
+void
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
- pixman_fixed_32_32_t x);
+ pixman_fixed_32_32_t x,
+ pixman_component_t *buffer);
/*
* Edges
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index b595ba7..62d26fc 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -66,7 +66,7 @@ fdot (double x1,
return x1 * x2 + y1 * y2 + z1 * z2;
}
-static uint32_t
+static void
radial_compute_color (double a,
double b,
double c,
@@ -74,7 +74,8 @@ radial_compute_color (double a,
double dr,
double mindr,
pixman_gradient_walker_t *walker,
- pixman_repeat_t repeat)
+ pixman_repeat_t repeat,
+ pixman_component_t *buffer)
{
/*
* In this function error propagation can lead to bad results:
@@ -96,8 +97,10 @@ radial_compute_color (double a,
if (a == 0)
{
- return _pixman_gradient_walker_pixel (walker,
- pixman_fixed_1 / 2 * c / b);
+ _pixman_gradient_walker_pixel (walker,
+ pixman_fixed_1 / 2 * c / b,
+ buffer);
+ return;
}
det = fdot (b, a, 0, b, -c, 0);
@@ -112,29 +115,35 @@ radial_compute_color (double a,
if (repeat == PIXMAN_REPEAT_NONE)
{
if (0 <= t0 && t0 <= pixman_fixed_1)
- return _pixman_gradient_walker_pixel (walker, t0);
+ _pixman_gradient_walker_pixel (walker, t0, buffer);
else if (0 <= t1 && t1 <= pixman_fixed_1)
- return _pixman_gradient_walker_pixel (walker, t1);
+ _pixman_gradient_walker_pixel (walker, t1, buffer);
+ else
+ memset (buffer, 0, sizeof (pixman_component_t) * 4);
}
else
{
if (t0 * dr > mindr)
- return _pixman_gradient_walker_pixel (walker, t0);
+ _pixman_gradient_walker_pixel (walker, t0, buffer);
else if (t1 * dr > mindr)
- return _pixman_gradient_walker_pixel (walker, t1);
+ _pixman_gradient_walker_pixel (walker, t1, buffer);
+ else
+ memset (buffer, 0, sizeof (pixman_component_t) * 4);
}
}
-
- return 0;
+ else
+ {
+ memset (buffer, 0, sizeof (pixman_component_t) * 4);
+ }
}
static void
-radial_gradient_get_scanline_32 (pixman_image_t *image,
- int x,
- int y,
- int width,
- uint32_t * buffer,
- const uint32_t *mask)
+radial_gradient_get_scanline (pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ pixman_component_t * buffer,
+ const pixman_component_t *mask)
{
/*
* Implementation of radial gradients following the PDF specification.
@@ -220,7 +229,6 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
gradient_t *gradient = (gradient_t *)image;
radial_gradient_t *radial = (radial_gradient_t *)image;
- uint32_t *end = buffer + width;
pixman_gradient_walker_t walker;
pixman_vector_t v, unit;
@@ -299,22 +307,23 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
unit.vector[0], unit.vector[1], 0);
- while (buffer < end)
+ while (width--)
{
if (!mask || *mask++)
{
- *buffer = radial_compute_color (radial->a, b, c,
- radial->inva,
- radial->delta.radius,
- radial->mindr,
- &walker,
- image->common.repeat);
+ radial_compute_color (radial->a, b, c,
+ radial->inva,
+ radial->delta.radius,
+ radial->mindr,
+ &walker,
+ image->common.repeat,
+ buffer);
}
b += db;
c += dc;
dc += ddc;
- ++buffer;
+ buffer += 4;
}
}
else
@@ -323,7 +332,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
/* Warning:
* error propagation guarantees are much looser than in the affine case
*/
- while (buffer < end)
+ while (width--)
{
if (!mask || *mask++)
{
@@ -348,20 +357,21 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
pdx, pdy, radial->c1.radius);
/* / pixman_fixed_1 / pixman_fixed_1 */
- *buffer = radial_compute_color (radial->a, b, c,
- radial->inva,
- radial->delta.radius,
- radial->mindr,
- &walker,
- image->common.repeat);
+ radial_compute_color (radial->a, b, c,
+ radial->inva,
+ radial->delta.radius,
+ radial->mindr,
+ &walker,
+ image->common.repeat,
+ buffer);
}
else
{
- *buffer = 0;
+ memset (buffer, 0, sizeof (pixman_component_t) * 4);
}
}
- ++buffer;
+ buffer += 4;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
@@ -373,8 +383,9 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
static void
radial_gradient_property_changed (pixman_image_t *image)
{
- image->common.get_scanline_32 = radial_gradient_get_scanline_32;
+ image->common.get_scanline_32 = _pixman_image_get_scanline_gradient_32;
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+ image->common.get_scanline = radial_gradient_get_scanline;
}
PIXMAN_EXPORT pixman_image_t *