[cairo-commit] cairo/pixman/src fbcompose.c, 1.4, 1.5 icimage.c,
1.33, 1.34 icimage.h, 1.28, 1.29 icint.h, 1.39, 1.40 pixman.h,
1.24, 1.25
Carl Worth
commit at pdx.freedesktop.org
Wed Jan 4 16:26:12 PST 2006
Committed by: cworth
Update of /cvs/cairo/cairo/pixman/src
In directory gabe:/tmp/cvs-serv16776/pixman/src
Modified Files:
fbcompose.c icimage.c icimage.h icint.h pixman.h
Log Message:
2006-01-04 Carl Worth <cworth at cworth.org>
Originally: 2005-10-10 David Reveman <davidr at novell.com>
* src/pixman.h: Add entries for gradient support.
* src/icint.h: Add PictureGradientColor.
* src/icimage.h:
* src/icimage.c: Add necessary functionality for gradient support.
* src/fbcompose.c: Enable gradient support.
Index: fbcompose.c
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/fbcompose.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- fbcompose.c 12 Sep 2005 12:55:11 -0000 1.4
+++ fbcompose.c 5 Jan 2006 00:26:10 -0000 1.5
@@ -33,8 +33,9 @@
#include "pixregionint.h"
+#include <math.h>
+
// #define PIXMAN_CONVOLUTION
-// #define PIXMAN_GRADIENTS
// #define PIXMAN_INDEXED_FORMATS
static Bool
@@ -2676,37 +2677,72 @@
#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
-#ifdef PIXMAN_GRADIENTS
+static CARD32
+xRenderColorMultToCard32 (pixman_color_t *c)
+{
+ return
+ ((((uint32_t) c->red * c->alpha) >> 24) << 16) |
+ ((((uint32_t) c->green * c->alpha) >> 24) << 8) |
+ ((((uint32_t) c->blue * c->alpha) >> 24) << 0) |
+ ((((uint32_t) c->alpha ) >> 8) << 24);
+}
+
static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
{
- int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16;
+ int ipos = (pos * pGradient->gradient.stopRange - 1) >> 16;
/* calculate the actual offset. */
- if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) {
- if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) {
- ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE;
- ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos;
+ if (ipos < 0 || ipos >= pGradient->gradient.stopRange)
+ {
+ if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal)
+ {
+ ipos = ipos % pGradient->gradient.stopRange;
+ ipos = ipos < 0 ? pGradient->gradient.stopRange + ipos : ipos;
- } else if (spread == RepeatReflect) {
- const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1;
- ipos = ipos % limit;
- ipos = ipos < 0 ? limit + ipos : ipos;
- ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
+ }
+ else if (spread == RepeatReflect)
+ {
+ const int limit = pGradient->gradient.stopRange * 2 - 1;
- } else if (spread == RepeatPad) {
- if (ipos < 0)
- ipos = 0;
- else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE)
- ipos = PICT_GRADIENT_STOPTABLE_SIZE-1;
- } else { /* RepeatNone */
- return 0;
- }
+ ipos = ipos % limit;
+ ipos = ipos < 0 ? limit + ipos : ipos;
+ ipos = ipos >= pGradient->gradient.stopRange ? limit - ipos : ipos;
+
+ }
+ else if (spread == RepeatPad)
+ {
+ if (ipos < 0)
+ ipos = 0;
+ else
+ ipos = pGradient->gradient.stopRange - 1;
+ }
+ else /* RepeatNone */
+ {
+ return 0;
+ }
}
- assert(ipos >= 0);
- assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE);
+ if (pGradient->gradient.colorTableSize)
+ {
+ return pGradient->gradient.colorTable[ipos];
+ }
+ else
+ {
+ int i;
- return pGradient->linear.colorTable[ipos];
+ if (ipos <= pGradient->gradient.stops->x)
+ return xRenderColorMultToCard32 (&pGradient->gradient.stops->color);
+
+ for (i = 1; i < pGradient->gradient.nstops; i++)
+ {
+ if (pGradient->gradient.stops[i].x >= ipos)
+ return PictureGradientColor (&pGradient->gradient.stops[i - 1],
+ &pGradient->gradient.stops[i],
+ ipos);
+ }
+
+ return xRenderColorMultToCard32 (&pGradient->gradient.stops[--i].color);
+ }
}
static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
@@ -2886,7 +2922,6 @@
}
}
}
-#endif /* PIXMAN_GRADIENTS */
static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
@@ -3457,10 +3492,8 @@
if (data->op == PIXMAN_OPERATOR_CLEAR)
fetchSrc = NULL;
else if (!data->src->pDrawable) {
-#ifdef PIXMAN_GRADIENTS
if (data->src->pSourcePict)
fetchSrc = fbFetchSourcePict;
-#endif
} else if (data->src->alphaMap)
fetchSrc = fbFetchExternalAlpha;
else if (data->src->repeat == RepeatNormal &&
@@ -3478,10 +3511,8 @@
if (data->mask && data->op != PIXMAN_OPERATOR_CLEAR) {
if (!data->mask->pDrawable) {
-#ifdef PIXMAN_GRADIENTS
if (data->mask->pSourcePict)
fetchMask = fbFetchSourcePict;
-#endif
} else if (data->mask->alphaMap)
fetchMask = fbFetchExternalAlpha;
else if (data->mask->repeat == RepeatNormal
Index: icimage.c
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/icimage.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- icimage.c 9 Oct 2005 16:09:53 -0000 1.33
+++ icimage.c 5 Jan 2006 00:26:10 -0000 1.34
@@ -101,6 +101,273 @@
return image;
}
+static CARD32 xRenderColorToCard32(pixman_color_t c)
+{
+ return
+ (c.alpha >> 8 << 24) |
+ (c.red >> 8 << 16) |
+ (c.green & 0xff00) |
+ (c.blue >> 8);
+}
+
+static uint premultiply(uint x)
+{
+ uint a = x >> 24;
+ uint t = (x & 0xff00ff) * a + 0x800080;
+ t = (t + ((t >> 8) & 0xff00ff)) >> 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a + 0x80;
+ x = (x + ((x >> 8) & 0xff));
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+
+static uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
+{
+ CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
+ t >>= 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
+ x &= 0xff00ff00;
+ x |= t;
+ return x;
+}
+
+uint32_t
+pixman_gradient_color (pixman_gradient_stop_t *stop1,
+ pixman_gradient_stop_t *stop2,
+ uint32_t x)
+{
+ uint32_t current_color, next_color;
+ int dist, idist;
+
+ current_color = xRenderColorToCard32 (stop1->color);
+ next_color = xRenderColorToCard32 (stop2->color);
+
+ dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
+ idist = 256 - dist;
+
+ return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
+ next_color, dist));
+}
+
+static int
+pixman_init_gradient_color_table (pixman_gradient_image_t *gradient,
+ int tableSize)
+{
+ int begin_pos, end_pos;
+ xFixed incr, dpos;
+ int pos, current_stop;
+ pixman_gradient_stop_t *stops = gradient->stops;
+ int nstops = gradient->nstops;
+
+ if (gradient->colorTableSize < tableSize)
+ {
+ uint32_t *newColorTable;
+
+ newColorTable = realloc (gradient->colorTable,
+ tableSize * sizeof (uint32_t));
+ if (!newColorTable)
+ return 1;
+
+ gradient->colorTable = newColorTable;
+ gradient->colorTableSize = tableSize;
+ }
+
+ gradient->stopRange = tableSize;
+
+ /* The position where the gradient begins and ends */
+ begin_pos = (stops[0].x * gradient->colorTableSize) >> 16;
+ end_pos = (stops[nstops - 1].x * gradient->colorTableSize) >> 16;
+
+ pos = 0; /* The position in the color table. */
+
+ /* Up to first point */
+ while (pos <= begin_pos) {
+ gradient->colorTable[pos] = xRenderColorToCard32(stops[0].color);
+ ++pos;
+ }
+
+ incr = (1<<16)/ gradient->colorTableSize; /* the double increment. */
+ dpos = incr * pos; /* The position in terms of 0-1. */
+
+ current_stop = 0; /* We always interpolate between current and current + 1. */
+
+ /* Gradient area */
+ while (pos < end_pos) {
+ gradient->colorTable[pos] =
+ pixman_gradient_color (&stops[current_stop],
+ &stops[current_stop + 1],
+ dpos);
+
+ ++pos;
+ dpos += incr;
+
+ if (dpos > stops[current_stop + 1].x)
+ ++current_stop;
+ }
+
+ /* After last point */
+ while (pos < gradient->colorTableSize) {
+ gradient->colorTable[pos] =
+ xRenderColorToCard32 (stops[nstops - 1].color);
+ ++pos;
+ }
+
+ return 0;
+}
+
+static int
+_pixman_init_gradient (pixman_gradient_image_t *gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops)
+{
+ pixman_fixed16_16_t dpos;
+ int i;
+
+ if (n_stops <= 0)
+ return 1;
+
+ dpos = -1;
+ for (i = 0; i < n_stops; i++)
+ {
+ if (stops[i].x < dpos || stops[i].x > (1 << 16))
+ return 1;
+
+ dpos = stops[i].x;
+ }
+
+ gradient->stopRange = 0xffff;
+ gradient->colorTable = NULL;
+ gradient->colorTableSize = 0;
+
+ return 0;
+}
+
+static pixman_image_t *
+_pixman_create_source_image (void)
+{
+ pixman_image_t *image;
+
+ image = (pixman_image_t *) malloc (sizeof (pixman_image_t));
+ image->pDrawable = 0;
+ image->pixels = 0;
+
+ pixman_image_init (image);
+
+ return image;
+}
+
+pixman_image_t *
+pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops)
+{
+ pixman_linear_gradient_image_t *linear;
+ pixman_image_t *image;
+
+ if (n_stops < 2)
+ return 0;
+
+ image = _pixman_create_source_image ();
+ if (!image)
+ return 0;
+
+ if (gradient->p1.x == gradient->p2.x && gradient->p1.y == gradient->p2.y)
+ return 0;
+
+ linear = malloc (sizeof (pixman_linear_gradient_image_t) +
+ sizeof (pixman_gradient_stop_t) * n_stops);
+ if (!linear)
+ {
+ free (image);
+ return 0;
+ }
+
+ linear->stops = (pixman_gradient_stop_t *) (linear + 1);
+ linear->nstops = n_stops;
+
+ memcpy (linear->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
+
+ linear->type = SourcePictTypeLinear;
+ linear->p1 = gradient->p1;
+ linear->p2 = gradient->p2;
+
+ image->pSourcePict = (pixman_source_image_t *) linear;
+
+ if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
+ {
+ free (image);
+ return 0;
+ }
+
+ return image;
+}
+
+pixman_image_t *
+pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops)
+{
+ pixman_radial_gradient_image_t *radial;
+ pixman_image_t *image;
+ double dx, dy, x;
+
+ if (n_stops < 2)
+ return 0;
+
+ image = _pixman_create_source_image ();
+ if (!image)
+ return 0;
+
+ dx = (double) (gradient->inner.x - gradient->outer.x);
+ dy = (double) (gradient->inner.y - gradient->outer.y);
+ if (sqrt (dx * dx + dy * dy) + (double) (gradient->inner.radius) >
+ (double) (gradient->outer.radius))
+ return 0;
+
+ radial = malloc (sizeof (pixman_radial_gradient_image_t) +
+ sizeof (pixman_gradient_stop_t) * n_stops);
+ if (!radial)
+ {
+ free (image);
+ return 0;
+ }
+
+ radial->stops = (pixman_gradient_stop_t *) (radial + 1);
+ radial->nstops = n_stops;
+
+ memcpy (radial->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
+
+ radial->type = SourcePictTypeRadial;
+ x = (double) gradient->inner.radius / (double) gradient->outer.radius;
+ radial->dx = (gradient->outer.x - gradient->inner.x);
+ radial->dy = (gradient->outer.y - gradient->inner.y);
+ radial->fx = (gradient->inner.x) - x * radial->dx;
+ radial->fy = (gradient->inner.y) - x * radial->dy;
+ radial->m = 1. / (1 + x);
+ radial->b = -x * radial->m;
+ radial->dx /= 65536.;
+ radial->dy /= 65536.;
+ radial->fx /= 65536.;
+ radial->fy /= 65536.;
+ x = gradient->outer.radius / 65536.;
+ radial->a = x * x - radial->dx * radial->dx - radial->dy * radial->dy;
+
+ image->pSourcePict = (pixman_source_image_t *) radial;
+
+ if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
+ {
+ free (image);
+ return 0;
+ }
+
+ return image;
+}
+
void
pixman_image_init (pixman_image_t *image)
{
@@ -135,16 +402,26 @@
image->serialNumber = GC_CHANGE_SERIAL_BIT;
*/
- image->pCompositeClip = pixman_region_create();
- pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
- 0, 0, image->pixels->width, image->pixels->height);
- image->freeCompClip = 1;
+ if (image->pixels)
+ {
+ image->pCompositeClip = pixman_region_create();
+ pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
+ 0, 0, image->pixels->width,
+ image->pixels->height);
+ image->freeCompClip = 1;
+
+ image->pSourceClip = pixman_region_create ();
+ pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
+ 0, 0, image->pixels->width,
+ image->pixels->height);
+ image->freeSourceClip = 1;
+ }
+ else
+ {
+ image->pCompositeClip = NULL;
+ image->pSourceClip = NULL;
+ }
- image->pSourceClip = pixman_region_create ();
- pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
- 0, 0, image->pixels->width, image->pixels->height);
- image->freeSourceClip = 1;
-
image->transform = NULL;
image->filter = PIXMAN_FILTER_NEAREST;
@@ -153,6 +430,8 @@
image->owns_pixels = 0;
+
+ image->pSourcePict = NULL;
}
void
@@ -218,25 +497,37 @@
int
pixman_image_get_width (pixman_image_t *image)
{
- return image->pixels->width;
+ if (image->pixels)
+ return image->pixels->width;
+
+ return 0;
}
int
pixman_image_get_height (pixman_image_t *image)
{
- return image->pixels->height;
+ if (image->pixels)
+ return image->pixels->height;
+
+ return 0;
}
int
pixman_image_get_depth (pixman_image_t *image)
{
- return image->pixels->depth;
+ if (image->pixels)
+ return image->pixels->depth;
+
+ return 0;
}
int
pixman_image_get_stride (pixman_image_t *image)
{
- return image->pixels->stride;
+ if (image->pixels)
+ return image->pixels->stride;
+
+ return 0;
}
pixman_format_t *
@@ -248,7 +539,10 @@
FbBits *
pixman_image_get_data (pixman_image_t *image)
{
- return image->pixels->data;
+ if (image->pixels)
+ return image->pixels->data;
+
+ return 0;
}
void
@@ -276,6 +570,11 @@
image->transform = NULL;
}
+ if (image->pSourcePict) {
+ free (image->pSourcePict);
+ image->pSourcePict = NULL;
+ }
+
free (image);
}
slim_hidden_def(pixman_image_destroy);
@@ -307,6 +606,10 @@
pixman_region_copy (image->clientClip, region);
image->clientClipType = CT_REGION;
}
+
+ image->stateChanges |= CPClipMask;
+ if (image->pSourcePict)
+ return 0;
if (image->freeCompClip)
pixman_region_destroy (image->pCompositeClip);
@@ -326,7 +629,6 @@
image->clipOrigin.y);
}
- image->stateChanges |= CPClipMask;
return 0;
}
@@ -378,7 +680,7 @@
if (image->transform)
return 1;
/* XXX davidr hates this, wants to never use source-based clipping */
- if (image->repeat != PIXMAN_REPEAT_NONE)
+ if (image->repeat != PIXMAN_REPEAT_NONE || image->pSourcePict)
{
/* XXX no source clipping */
if (image->compositeClipSource &&
Index: icimage.h
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/icimage.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- icimage.h 9 Oct 2005 21:29:54 -0000 1.28
+++ icimage.h 5 Jan 2006 00:26:10 -0000 1.29
@@ -54,6 +54,76 @@
} pixman_format_t;
*/
+#define PICT_GRADIENT_STOPTABLE_SIZE 1024
+
+#define SourcePictTypeSolidFill 0
+#define SourcePictTypeLinear 1
+#define SourcePictTypeRadial 2
+#define SourcePictTypeConical 3
+
+typedef struct _pixman_solid_fill_image {
+ unsigned int type;
+ uint32_t color;
+} pixman_solid_fill_image_t;
+
+typedef struct _pixman_gradient_image {
+ unsigned int type;
+ pixman_gradient_stop_t *stops;
+ int nstops;
+ int stopRange;
+ uint32_t *colorTable;
+ int colorTableSize;
+} pixman_gradient_image_t;
+
+typedef struct _pixman_linear_gradient_image {
+ unsigned int type;
+ pixman_gradient_stop_t *stops;
+ int nstops;
+ int stopRange;
+ uint32_t *colorTable;
+ int colorTableSize;
+ pixman_point_fixed_t p1;
+ pixman_point_fixed_t p2;
+} pixman_linear_gradient_image_t;
+
+typedef struct _pixman_radial_gradient_image {
+ unsigned int type;
+ pixman_gradient_stop_t *stops;
+ int nstops;
+ int stopRange;
+ uint32_t *colorTable;
+ int colorTableSize;
+ double fx;
+ double fy;
+ double dx;
+ double dy;
+ double a;
+ double m;
+ double b;
+} pixman_radial_gradient_image_t;
+
+typedef struct _pixman_conical_gradient_image {
+ unsigned int type;
+ pixman_gradient_stop_t *stops;
+ int nstops;
+ int stopRange;
+ uint32_t *colorTable;
+ int colorTableSize;
+ pixman_point_fixed_t center;
+ pixman_fixed16_16_t angle;
+} pixman_conical_gradient_image_t;
+
+typedef union _pixman_source_image {
+ unsigned int type;
+ pixman_solid_fill_image_t solidFill;
+ pixman_gradient_image_t gradient;
+ pixman_linear_gradient_image_t linear;
+ pixman_radial_gradient_image_t radial;
+ pixman_conical_gradient_image_t conical;
+} pixman_source_image_t;
+
+typedef pixman_source_image_t *SourcePictPtr;
+
struct pixman_image {
FbPixels *pixels;
pixman_format_t image_format;
@@ -93,6 +163,8 @@
int filter_nparams;
int owns_pixels;
+
+ pixman_source_image_t *pSourcePict;
};
#endif /* _ICIMAGE_H_ */
Index: icint.h
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/icint.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- icint.h 16 Aug 2005 23:50:25 -0000 1.39
+++ icint.h 5 Jan 2006 00:26:10 -0000 1.40
@@ -835,6 +835,13 @@
pixman_image_createForPixels (FbPixels *pixels,
pixman_format_t *format);
+pixman_private uint32_t
+pixman_gradient_color (pixman_gradient_stop_t *stop1,
+ pixman_gradient_stop_t *stop2,
+ uint32_t x);
+
+#define PictureGradientColor pixman_gradient_color
+
/* icpixels.c */
pixman_private FbPixels *
Index: pixman.h
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/pixman.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- pixman.h 9 Oct 2005 16:09:53 -0000 1.24
+++ pixman.h 5 Jan 2006 00:26:10 -0000 1.25
@@ -332,6 +332,34 @@
pixman_fixed16_16_t matrix[3][3];
} pixman_transform_t;
+typedef struct pixman_color {
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+ unsigned short alpha;
+} pixman_color_t;
+
+typedef struct _pixman_gradient_stop {
+ pixman_fixed16_16_t x;
+ pixman_color_t color;
+} pixman_gradient_stop_t;
+
+typedef struct _pixman_circle {
+ pixman_fixed16_16_t x;
+ pixman_fixed16_16_t y;
+ pixman_fixed16_16_t radius;
+} pixman_circle_t;
+
+typedef struct pixman_linear_gradient {
+ pixman_point_fixed_t p1;
+ pixman_point_fixed_t p2;
+} pixman_linear_gradient_t;
+
+typedef struct pixman_radial_gradient {
+ pixman_circle_t inner;
+ pixman_circle_t outer;
+} pixman_radial_gradient_t;
+
typedef enum {
PIXMAN_FILTER_FAST,
PIXMAN_FILTER_GOOD,
@@ -382,15 +410,17 @@
pixman_bits_t *
pixman_image_get_data (pixman_image_t *image);
-/* iccolor.c */
+pixman_image_t *
+pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops);
-/* XXX: Do we really need a struct here? Only pixman_rectangle_t uses this. */
-typedef struct pixman_color {
- unsigned short red;
- unsigned short green;
- unsigned short blue;
- unsigned short alpha;
-} pixman_color_t;
+pixman_image_t *
+pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
+ const pixman_gradient_stop_t *stops,
+ int n_stops);
+
+/* iccolor.c */
void
pixman_color_to_pixel (const pixman_format_t *format,
More information about the cairo-commit
mailing list