summaryrefslogtreecommitdiff
path: root/x11/pixman
diff options
context:
space:
mode:
authorbjs <bjs>2008-02-18 05:36:51 +0000
committerbjs <bjs>2008-02-18 05:36:51 +0000
commitf4388abe2688a1b17871faefe1d87a071462e629 (patch)
tree304eebcb56db726e0bbcde24b8dd3f08e49ec076 /x11/pixman
parent46575984c6e5731831e45e30eef4a4418d414efb (diff)
downloadpkgsrc-f4388abe2688a1b17871faefe1d87a071462e629.tar.gz
Fix a null pointer dereference, some warnings, and add refactored code
for FbFetchTransformed() from GIT. Bump rev.
Diffstat (limited to 'x11/pixman')
-rw-r--r--x11/pixman/Makefile4
-rw-r--r--x11/pixman/distinfo4
-rw-r--r--x11/pixman/patches/patch-aa1045
-rw-r--r--x11/pixman/patches/patch-ab13
4 files changed, 1063 insertions, 3 deletions
diff --git a/x11/pixman/Makefile b/x11/pixman/Makefile
index d8c5a4f9d04..d2701a84388 100644
--- a/x11/pixman/Makefile
+++ b/x11/pixman/Makefile
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.5 2008/02/07 06:40:27 bjs Exp $
+# $NetBSD: Makefile,v 1.6 2008/02/18 05:36:51 bjs Exp $
#
DISTNAME= pixman-0.9.6
-PKGREVISION= 4
+PKGREVISION= 5
CATEGORIES= x11
MASTER_SITES= ${MASTER_SITE_LOCAL}
EXTRACT_SUFX= .tar.bz2
diff --git a/x11/pixman/distinfo b/x11/pixman/distinfo
index a832e168b54..8b20fd08f93 100644
--- a/x11/pixman/distinfo
+++ b/x11/pixman/distinfo
@@ -1,5 +1,7 @@
-$NetBSD: distinfo,v 1.5 2008/02/07 06:40:27 bjs Exp $
+$NetBSD: distinfo,v 1.6 2008/02/18 05:36:51 bjs Exp $
SHA1 (pixman-0.9.6.tar.bz2) = 9dc40e9c1610080a92b054cdbf1c417f605eb5ce
RMD160 (pixman-0.9.6.tar.bz2) = 928e18c06b959b6e7cb7f13ebf113fd2d8cf9493
Size (pixman-0.9.6.tar.bz2) = 281291 bytes
+SHA1 (patch-aa) = df0b5e160aaa382a5671c67db36cfafe93c6f9c6
+SHA1 (patch-ab) = b0404cfca7ed89c433aff34d9c5e0ab02b4495df
diff --git a/x11/pixman/patches/patch-aa b/x11/pixman/patches/patch-aa
new file mode 100644
index 00000000000..dbe8e21bf51
--- /dev/null
+++ b/x11/pixman/patches/patch-aa
@@ -0,0 +1,1045 @@
+$NetBSD: patch-aa,v 1.4 2008/02/18 05:36:51 bjs Exp $
+
+--- pixman/pixman-compose.c.orig 2008-02-18 00:32:50.000000000 -0500
++++ pixman/pixman-compose.c
+@@ -3678,19 +3678,516 @@ static void pixmanFetchSourcePict(source
+ }
+ }
+
+-static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
++/*
++ * Fetch from region strategies
++ */
++typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box);
++
++static inline uint32_t
++fbFetchFromNoRegion(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
+ {
+- uint32_t *bits;
+- int32_t stride;
++ return fetch (pict, x, y);
++}
++
++static uint32_t
++fbFetchFromNRectangles(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
++{
++ pixman_box16_t box2;
++ if (pixman_region_contains_point (pict->common.src_clip, x, y, &box2))
++ return fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
++ else
++ return 0;
++}
++
++static uint32_t
++fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
++{
++ pixman_box16_t box2 = *box;
++ return ((x < box2.x1) | (x >= box2.x2) | (y < box2.y1) | (y >= box2.y2)) ?
++ 0 : fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
++}
++
++/*
++ * Fetching Algorithms
++ */
++static void
++fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t* box = NULL;
+ fetchPixelProc fetch;
+- pixman_vector_t v;
+- pixman_vector_t unit;
+- int i;
+- pixman_box16_t box;
+- pixman_bool_t affine = TRUE;
++ fetchFromRegionProc fetchFromRegion;
++ int x, y, i;
++
++ /* initialize the two function pointers */
++ fetch = fetchPixelProcForPicture(pict);
++
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ fetchFromRegion = fbFetchFromNoRegion;
++ else
++ fetchFromRegion = fbFetchFromNRectangles;
++
++ for ( i = 0; i < width; ++i)
++ {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2])
++ {
++ *(buffer + i) = 0;
++ }
++ else
++ {
++ if (!affine)
++ {
++ y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
++ x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
++ }
++ else
++ {
++ y = MOD(v.vector[1]>>16, pict->height);
++ x = MOD(v.vector[0]>>16, pict->width);
++ }
++ *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
++ }
++ }
++
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ fetchFromRegionProc fetchFromRegion;
++ int x, y, i;
++
++ /* initialize the two function pointers */
++ fetch = fetchPixelProcForPicture(pict);
++
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ fetchFromRegion = fbFetchFromNoRegion;
++ else
++ fetchFromRegion = fbFetchFromNRectangles;
++
++ for (i = 0; i < width; ++i)
++ {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2])
++ {
++ *(buffer + i) = 0;
++ }
++ else
++ {
++ if (!affine)
++ {
++ y = CLIP(DIV(v.vector[1], v.vector[2]), 0, pict->height-1);
++ x = CLIP(DIV(v.vector[0], v.vector[2]), 0, pict->width-1);
++ }
++ else
++ {
++ y = CLIP(v.vector[1]>>16, 0, pict->height-1);
++ x = CLIP(v.vector[0]>>16, 0, pict->width-1);
++ }
++
++ *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
++ }
++ }
++
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ fetchFromRegionProc fetchFromRegion;
++ int x, y, i;
+
++ /* initialize the two function pointers */
+ fetch = fetchPixelProcForPicture(pict);
+
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ {
++ box = &(pict->common.src_clip->extents);
++ fetchFromRegion = fbFetchFromOneRectangle;
++ }
++ else
++ {
++ fetchFromRegion = fbFetchFromNRectangles;
++ }
++
++ for (i = 0; i < width; ++i) {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2]) {
++ *(buffer + i) = 0;
++ } else {
++ if (!affine) {
++ y = DIV(v.vector[1],v.vector[2]);
++ x = DIV(v.vector[0],v.vector[2]);
++ } else {
++ y = v.vector[1]>>16;
++ x = v.vector[0]>>16;
++ }
++ *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
++ }
++ }
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ fetchFromRegionProc fetchFromRegion;
++ int i;
++
++ /* initialize the two function pointers */
++ fetch = fetchPixelProcForPicture(pict);
++
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ fetchFromRegion = fbFetchFromNoRegion;
++ else
++ fetchFromRegion = fbFetchFromNRectangles;
++
++ for (i = 0; i < width; ++i) {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2]) {
++ *(buffer + i) = 0;
++ } else {
++ int x1, x2, y1, y2, distx, idistx, disty, idisty;
++ uint32_t tl, tr, bl, br, r;
++ uint32_t ft, fb;
++
++ if (!affine) {
++ pixman_fixed_48_16_t div;
++ div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
++ x1 = div >> 16;
++ distx = ((pixman_fixed_t)div >> 8) & 0xff;
++ div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
++ y1 = div >> 16;
++ disty = ((pixman_fixed_t)div >> 8) & 0xff;
++ } else {
++ x1 = v.vector[0] >> 16;
++ distx = (v.vector[0] >> 8) & 0xff;
++ y1 = v.vector[1] >> 16;
++ disty = (v.vector[1] >> 8) & 0xff;
++ }
++ x2 = x1 + 1;
++ y2 = y1 + 1;
++
++ idistx = 256 - distx;
++ idisty = 256 - disty;
++
++ x1 = MOD (x1, pict->width);
++ x2 = MOD (x2, pict->width);
++ y1 = MOD (y1, pict->height);
++ y2 = MOD (y2, pict->height);
++
++ tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
++ tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
++ bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
++ br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
++
++ ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
++ fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
++ r = (((ft * idisty + fb * disty) >> 16) & 0xff);
++ ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
++ fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
++ r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
++ ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
++ fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
++ r |= (((ft * idisty + fb * disty)) & 0xff0000);
++ ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
++ fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
++ r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
++ *(buffer + i) = r;
++ }
++ }
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ fetchFromRegionProc fetchFromRegion;
++ int i;
++
++ /* initialize the two function pointers */
++ fetch = fetchPixelProcForPicture(pict);
++
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ fetchFromRegion = fbFetchFromNoRegion;
++ else
++ fetchFromRegion = fbFetchFromNRectangles;
++
++ for (i = 0; i < width; ++i) {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2]) {
++ *(buffer + i) = 0;
++ } else {
++ int x1, x2, y1, y2, distx, idistx, disty, idisty;
++ uint32_t tl, tr, bl, br, r;
++ uint32_t ft, fb;
++
++ if (!affine) {
++ pixman_fixed_48_16_t div;
++ div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
++ x1 = div >> 16;
++ distx = ((pixman_fixed_t)div >> 8) & 0xff;
++ div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
++ y1 = div >> 16;
++ disty = ((pixman_fixed_t)div >> 8) & 0xff;
++ } else {
++ x1 = v.vector[0] >> 16;
++ distx = (v.vector[0] >> 8) & 0xff;
++ y1 = v.vector[1] >> 16;
++ disty = (v.vector[1] >> 8) & 0xff;
++ }
++ x2 = x1 + 1;
++ y2 = y1 + 1;
++
++ idistx = 256 - distx;
++ idisty = 256 - disty;
++
++ x1 = CLIP (x1, 0, pict->width-1);
++ x2 = CLIP (x2, 0, pict->width-1);
++ y1 = CLIP (y1, 0, pict->height-1);
++ y2 = CLIP (y2, 0, pict->height-1);
++
++ tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
++ tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
++ bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
++ br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
++
++ ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
++ fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
++ r = (((ft * idisty + fb * disty) >> 16) & 0xff);
++ ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
++ fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
++ r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
++ ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
++ fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
++ r |= (((ft * idisty + fb * disty)) & 0xff0000);
++ ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
++ fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
++ r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
++ *(buffer + i) = r;
++ }
++ }
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ fetchFromRegionProc fetchFromRegion;
++ int i;
++
++ /* initialize the two function pointers */
++ fetch = fetchPixelProcForPicture(pict);
++
++ if(pixman_region_n_rects (pict->common.src_clip) == 1)
++ {
++ box = &(pict->common.src_clip->extents);
++ fetchFromRegion = fbFetchFromOneRectangle;
++ }
++ else
++ {
++ fetchFromRegion = fbFetchFromNRectangles;
++ }
++
++ for (i = 0; i < width; ++i)
++ {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2]) {
++ *(buffer + i) = 0;
++ } else {
++ int x1, x2, y1, y2, distx, idistx, disty, idisty;
++ uint32_t tl, tr, bl, br, r;
++ uint32_t ft, fb;
++
++ if (!affine) {
++ pixman_fixed_48_16_t div;
++ div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
++ x1 = div >> 16;
++ distx = ((pixman_fixed_t)div >> 8) & 0xff;
++ div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
++ y1 = div >> 16;
++ disty = ((pixman_fixed_t)div >> 8) & 0xff;
++ } else {
++ x1 = v.vector[0] >> 16;
++ distx = (v.vector[0] >> 8) & 0xff;
++ y1 = v.vector[1] >> 16;
++ disty = (v.vector[1] >> 8) & 0xff;
++ }
++ x2 = x1 + 1;
++ y2 = y1 + 1;
++
++ idistx = 256 - distx;
++ idisty = 256 - disty;
++
++ tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
++ tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
++ bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
++ br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
++
++ ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
++ fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
++ r = (((ft * idisty + fb * disty) >> 16) & 0xff);
++ ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
++ fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
++ r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
++ ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
++ fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
++ r |= (((ft * idisty + fb * disty)) & 0xff0000);
++ ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
++ fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
++ r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
++ *(buffer + i) = r;
++ }
++ }
++
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
++{
++ pixman_box16_t *box = NULL;
++ fetchPixelProc fetch;
++ int i;
++
++ pixman_fixed_t *params = pict->common.filter_params;
++ int32_t cwidth = pixman_fixed_to_int(params[0]);
++ int32_t cheight = pixman_fixed_to_int(params[1]);
++ int xoff = (params[0] - pixman_fixed_1) >> 1;
++ int yoff = (params[1] - pixman_fixed_1) >> 1;
++ fetch = fetchPixelProcForPicture(pict);
++
++ params += 2;
++ for (i = 0; i < width; ++i) {
++ if (!mask || mask[i] & maskBits)
++ {
++ if (!v.vector[2]) {
++ *(buffer + i) = 0;
++ } else {
++ int x1, x2, y1, y2, x, y;
++ int32_t srtot, sgtot, sbtot, satot;
++ pixman_fixed_t *p = params;
++
++ if (!affine) {
++ pixman_fixed_48_16_t tmp;
++ tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff;
++ x1 = pixman_fixed_to_int(tmp);
++ tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff;
++ y1 = pixman_fixed_to_int(tmp);
++ } else {
++ x1 = pixman_fixed_to_int(v.vector[0] - xoff);
++ y1 = pixman_fixed_to_int(v.vector[1] - yoff);
++ }
++ x2 = x1 + cwidth;
++ y2 = y1 + cheight;
++
++ srtot = sgtot = sbtot = satot = 0;
++
++ for (y = y1; y < y2; y++) {
++ int ty;
++ switch (pict->common.repeat) {
++ case PIXMAN_REPEAT_NORMAL:
++ ty = MOD (y, pict->height);
++ break;
++ case PIXMAN_REPEAT_PAD:
++ ty = CLIP (y, 0, pict->height-1);
++ break;
++ default:
++ ty = y;
++ }
++ for (x = x1; x < x2; x++) {
++ if (*p) {
++ int tx;
++ switch (pict->common.repeat) {
++ case PIXMAN_REPEAT_NORMAL:
++ tx = MOD (x, pict->width);
++ break;
++ case PIXMAN_REPEAT_PAD:
++ tx = CLIP (x, 0, pict->width-1);
++ break;
++ default:
++ tx = x;
++ }
++ if (pixman_region_contains_point (pict->common.src_clip, tx, ty, box)) {
++ uint32_t c = fetch(pict, tx, ty);
++
++ srtot += Red(c) * *p;
++ sgtot += Green(c) * *p;
++ sbtot += Blue(c) * *p;
++ satot += Alpha(c) * *p;
++ }
++ }
++ p++;
++ }
++ }
++
++ satot >>= 16;
++ srtot >>= 16;
++ sgtot >>= 16;
++ sbtot >>= 16;
++
++ if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
++ if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
++ if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
++ if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
++
++ *(buffer + i) = ((satot << 24) |
++ (srtot << 16) |
++ (sgtot << 8) |
++ (sbtot ));
++ }
++ }
++ v.vector[0] += unit.vector[0];
++ v.vector[1] += unit.vector[1];
++ v.vector[2] += unit.vector[2];
++ }
++}
++
++static void
++fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
++{
++ uint32_t *bits;
++ int32_t stride;
++ pixman_vector_t v;
++ pixman_vector_t unit;
++ pixman_bool_t affine = TRUE;
++
+ bits = pict->bits;
+ stride = pict->rowstride;
+
+@@ -3703,7 +4200,7 @@ static void fbFetchTransformed(bits_imag
+ if (pict->common.transform)
+ {
+ if (!pixman_transform_point_3d (pict->common.transform, &v))
+- {
++ {
+ fbFinishAccess (pict->pDrawable);
+ return;
+ }
+@@ -3721,104 +4218,18 @@ static void fbFetchTransformed(bits_imag
+
+ if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST)
+ {
+- if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
+- if (pixman_region_n_rects (pict->common.src_clip) == 1) {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- if (!affine) {
+- y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
+- x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
+- } else {
+- y = MOD(v.vector[1]>>16, pict->height);
+- x = MOD(v.vector[0]>>16, pict->width);
+- }
+- *(buffer + i) = fetch(pict, x, y);
+- }
+- }
++ if (pict->common.repeat == PIXMAN_REPEAT_NORMAL)
++ {
++ fbFetchTransformed_Nearest_Normal(pict, width, buffer, mask, maskBits, affine, v, unit);
+
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- } else {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- if (!affine) {
+- y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
+- x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
+- } else {
+- y = MOD(v.vector[1]>>16, pict->height);
+- x = MOD(v.vector[0]>>16, pict->width);
+- }
+- if (pixman_region_contains_point (pict->common.src_clip, x, y, &box))
+- *(buffer + i) = fetch (pict, x, y);
+- else
+- *(buffer + i) = 0;
+- }
+- }
+-
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- }
+- } else {
+- if (pixman_region_n_rects(pict->common.src_clip) == 1) {
+- box = pict->common.src_clip->extents;
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- if (!affine) {
+- y = DIV(v.vector[1],v.vector[2]);
+- x = DIV(v.vector[0],v.vector[2]);
+- } else {
+- y = v.vector[1]>>16;
+- x = v.vector[0]>>16;
+- }
+- *(buffer + i) = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
+- 0 : fetch(pict, x, y);
+- }
+- }
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- } else {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- if (!affine) {
+- y = DIV(v.vector[1],v.vector[2]);
+- x = DIV(v.vector[0],v.vector[2]);
+- } else {
+- y = v.vector[1]>>16;
+- x = v.vector[0]>>16;
+- }
+- if (pixman_region_contains_point (pict->common.src_clip, x, y, &box))
+- *(buffer + i) = fetch(pict, x, y);
+- else
+- *(buffer + i) = 0;
+- }
+- }
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- }
++ }
++ else if (pict->common.repeat == PIXMAN_REPEAT_PAD)
++ {
++ fbFetchTransformed_Nearest_Pad(pict, width, buffer, mask, maskBits, affine, v, unit);
++ }
++ else
++ {
++ fbFetchTransformed_Nearest_General(pict, width, buffer, mask, maskBits, affine, v, unit);
+ }
+ } else if (pict->common.filter == PIXMAN_FILTER_BILINEAR ||
+ pict->common.filter == PIXMAN_FILTER_GOOD ||
+@@ -3830,336 +4241,30 @@ static void fbFetchTransformed(bits_imag
+ unit.vector[0] -= unit.vector[2] / 2;
+ unit.vector[1] -= unit.vector[2] / 2;
+
+- if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
+- if (pixman_region_n_rects(pict->common.src_clip) == 1) {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- int x1, x2, y1, y2, distx, idistx, disty, idisty;
+- uint32_t tl, tr, bl, br, r;
+- uint32_t ft, fb;
+-
+- if (!affine) {
+- pixman_fixed_48_16_t div;
+- div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+- x1 = div >> 16;
+- distx = ((pixman_fixed_t)div >> 8) & 0xff;
+- div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+- y1 = div >> 16;
+- disty = ((pixman_fixed_t)div >> 8) & 0xff;
+- } else {
+- x1 = v.vector[0] >> 16;
+- distx = (v.vector[0] >> 8) & 0xff;
+- y1 = v.vector[1] >> 16;
+- disty = (v.vector[1] >> 8) & 0xff;
+- }
+- x2 = x1 + 1;
+- y2 = y1 + 1;
+-
+- idistx = 256 - distx;
+- idisty = 256 - disty;
+-
+- x1 = MOD (x1, pict->width);
+- x2 = MOD (x2, pict->width);
+- y1 = MOD (y1, pict->height);
+- y2 = MOD (y2, pict->height);
+-
+- tl = fetch(pict, x1, y1);
+- tr = fetch(pict, x2, y1);
+- bl = fetch(pict, x1, y2);
+- br = fetch(pict, x2, y2);
+-
+- ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+- fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+- r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+- ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+- fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+- r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+- ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+- fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+- r |= (((ft * idisty + fb * disty)) & 0xff0000);
+- ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+- fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+- r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+- *(buffer + i) = r;
+- }
+- }
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- } else {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- int x1, x2, y1, y2, distx, idistx, disty, idisty;
+- uint32_t tl, tr, bl, br, r;
+- uint32_t ft, fb;
+-
+- if (!affine) {
+- pixman_fixed_48_16_t div;
+- div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+- x1 = div >> 16;
+- distx = ((pixman_fixed_t)div >> 8) & 0xff;
+- div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+- y1 = div >> 16;
+- disty = ((pixman_fixed_t)div >> 8) & 0xff;
+- } else {
+- x1 = v.vector[0] >> 16;
+- distx = (v.vector[0] >> 8) & 0xff;
+- y1 = v.vector[1] >> 16;
+- disty = (v.vector[1] >> 8) & 0xff;
+- }
+- x2 = x1 + 1;
+- y2 = y1 + 1;
+-
+- idistx = 256 - distx;
+- idisty = 256 - disty;
+-
+- x1 = MOD (x1, pict->width);
+- x2 = MOD (x2, pict->width);
+- y1 = MOD (y1, pict->height);
+- y2 = MOD (y2, pict->height);
+-
+- tl = pixman_region_contains_point(pict->common.src_clip, x1, y1, &box)
+- ? fetch(pict, x1, y1) : 0;
+- tr = pixman_region_contains_point(pict->common.src_clip, x2, y1, &box)
+- ? fetch(pict, x2, y1) : 0;
+- bl = pixman_region_contains_point(pict->common.src_clip, x1, y2, &box)
+- ? fetch(pict, x1, y2) : 0;
+- br = pixman_region_contains_point(pict->common.src_clip, x2, y2, &box)
+- ? fetch(pict, x2, y2) : 0;
+-
+- ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+- fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+- r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+- ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+- fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+- r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+- ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+- fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+- r |= (((ft * idisty + fb * disty)) & 0xff0000);
+- ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+- fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+- r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+- *(buffer + i) = r;
+- }
+- }
+-
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- }
+- } else {
+- if (pixman_region_n_rects(pict->common.src_clip) == 1) {
+- box = pict->common.src_clip->extents;
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- int x1, x2, y1, y2, distx, idistx, disty, idisty;
+- uint32_t tl, tr, bl, br, r;
+- pixman_bool_t x1_out, x2_out, y1_out, y2_out;
+- uint32_t ft, fb;
+-
+- if (!affine) {
+- pixman_fixed_48_16_t div;
+- div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+- x1 = div >> 16;
+- distx = ((pixman_fixed_t)div >> 8) & 0xff;
+- div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+- y1 = div >> 16;
+- disty = ((pixman_fixed_t)div >> 8) & 0xff;
+- } else {
+- x1 = v.vector[0] >> 16;
+- distx = (v.vector[0] >> 8) & 0xff;
+- y1 = v.vector[1] >> 16;
+- disty = (v.vector[1] >> 8) & 0xff;
+- }
+- x2 = x1 + 1;
+- y2 = y1 + 1;
+-
+- idistx = 256 - distx;
+- idisty = 256 - disty;
+-
+- x1_out = (x1 < box.x1) | (x1 >= box.x2);
+- x2_out = (x2 < box.x1) | (x2 >= box.x2);
+- y1_out = (y1 < box.y1) | (y1 >= box.y2);
+- y2_out = (y2 < box.y1) | (y2 >= box.y2);
+-
+- tl = x1_out|y1_out ? 0 : fetch(pict, x1, y1);
+- tr = x2_out|y1_out ? 0 : fetch(pict, x2, y1);
+- bl = x1_out|y2_out ? 0 : fetch(pict, x1, y2);
+- br = x2_out|y2_out ? 0 : fetch(pict, x2, y2);
+-
+- ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+- fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+- r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+- ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+- fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+- r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+- ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+- fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+- r |= (((ft * idisty + fb * disty)) & 0xff0000);
+- ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+- fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+- r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+- *(buffer + i) = r;
+- }
+- }
+-
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- } else {
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- int x1, x2, y1, y2, distx, idistx, disty, idisty;
+- uint32_t tl, tr, bl, br, r;
+- uint32_t ft, fb;
+-
+- if (!affine) {
+- pixman_fixed_48_16_t div;
+- div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+- x1 = div >> 16;
+- distx = ((pixman_fixed_t)div >> 8) & 0xff;
+- div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+- y1 = div >> 16;
+- disty = ((pixman_fixed_t)div >> 8) & 0xff;
+- } else {
+- x1 = v.vector[0] >> 16;
+- distx = (v.vector[0] >> 8) & 0xff;
+- y1 = v.vector[1] >> 16;
+- disty = (v.vector[1] >> 8) & 0xff;
+- }
+- x2 = x1 + 1;
+- y2 = y1 + 1;
+-
+- idistx = 256 - distx;
+- idisty = 256 - disty;
+-
+- tl = pixman_region_contains_point(pict->common.src_clip, x1, y1, &box)
+- ? fetch(pict, x1, y1) : 0;
+- tr = pixman_region_contains_point(pict->common.src_clip, x2, y1, &box)
+- ? fetch(pict, x2, y1) : 0;
+- bl = pixman_region_contains_point(pict->common.src_clip, x1, y2, &box)
+- ? fetch(pict, x1, y2) : 0;
+- br = pixman_region_contains_point(pict->common.src_clip, x2, y2, &box)
+- ? fetch(pict, x2, y2) : 0;
+-
+- ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+- fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+- r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+- ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+- fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+- r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+- ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+- fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+- r |= (((ft * idisty + fb * disty)) & 0xff0000);
+- ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+- fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+- r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+- *(buffer + i) = r;
+- }
+- }
+-
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
+- }
+- }
++ if (pict->common.repeat == PIXMAN_REPEAT_NORMAL)
++ {
++ fbFetchTransformed_Bilinear_Normal(pict, width, buffer, mask, maskBits, affine, v, unit);
+ }
+- } else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) {
+- pixman_fixed_t *params = pict->common.filter_params;
+- int32_t cwidth = pixman_fixed_to_int(params[0]);
+- int32_t cheight = pixman_fixed_to_int(params[1]);
+- int xoff = (params[0] - pixman_fixed_1) >> 1;
+- int yoff = (params[1] - pixman_fixed_1) >> 1;
+- params += 2;
+- for (i = 0; i < width; ++i) {
+- if (!mask || mask[i] & maskBits)
+- {
+- if (!v.vector[2]) {
+- *(buffer + i) = 0;
+- } else {
+- int x1, x2, y1, y2, x, y;
+- int32_t srtot, sgtot, sbtot, satot;
+- pixman_fixed_t *p = params;
+-
+- if (!affine) {
+- pixman_fixed_48_16_t tmp;
+- tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff;
+- x1 = pixman_fixed_to_int(tmp);
+- tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff;
+- y1 = pixman_fixed_to_int(tmp);
+- } else {
+- x1 = pixman_fixed_to_int(v.vector[0] - xoff);
+- y1 = pixman_fixed_to_int(v.vector[1] - yoff);
+- }
+- x2 = x1 + cwidth;
+- y2 = y1 + cheight;
+-
+- srtot = sgtot = sbtot = satot = 0;
+-
+- for (y = y1; y < y2; y++) {
+- int ty = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (y, pict->height) : y;
+- for (x = x1; x < x2; x++) {
+- if (*p) {
+- int tx = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (x, pict->width) : x;
+- if (pixman_region_contains_point (pict->common.src_clip, tx, ty, &box)) {
+- uint32_t c = fetch(pict, tx, ty);
+-
+- srtot += Red(c) * *p;
+- sgtot += Green(c) * *p;
+- sbtot += Blue(c) * *p;
+- satot += Alpha(c) * *p;
+- }
+- }
+- p++;
+- }
+- }
+-
+- satot >>= 16;
+- srtot >>= 16;
+- sgtot >>= 16;
+- sbtot >>= 16;
+-
+- if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
+- if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
+- if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
+- if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
+-
+- *(buffer + i) = ((satot << 24) |
+- (srtot << 16) |
+- (sgtot << 8) |
+- (sbtot ));
+- }
+- }
+- v.vector[0] += unit.vector[0];
+- v.vector[1] += unit.vector[1];
+- v.vector[2] += unit.vector[2];
++ else if (pict->common.repeat == PIXMAN_REPEAT_PAD)
++ {
++ fbFetchTransformed_Bilinear_Pad(pict, width, buffer, mask, maskBits, affine, v, unit);
+ }
++ else
++ {
++ fbFetchTransformed_Bilinear_General(pict, width, buffer, mask, maskBits, affine, v, unit);
++ }
++ }
++ else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION)
++ {
++ fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit);
+ }
+
+ fbFinishAccess (pict->pDrawable);
+ }
+
+
+-static void fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
++static void
++fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
+ {
+ int i;
+ uint32_t _alpha_buffer[SCANLINE_BUFFER_LENGTH];
+@@ -4191,7 +4296,8 @@ static void fbFetchExternalAlpha(bits_im
+ free(alpha_buffer);
+ }
+
+-static void fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
++static void
++fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
+ {
+ uint32_t *bits;
+ int32_t stride;
+@@ -4205,7 +4311,8 @@ static void fbStore(bits_image_t * pict,
+ fbFinishAccess (pict->pDrawable);
+ }
+
+-static void fbStoreExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
++static void
++fbStoreExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
+ {
+ uint32_t *bits, *alpha_bits;
+ int32_t stride, astride;
+@@ -4284,7 +4391,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbC
+ {
+ fetchSrc = (scanFetchProc)fbFetchExternalAlpha;
+ }
+- else if (bits->common.repeat == PIXMAN_REPEAT_NORMAL &&
++ else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
+ bits->width == 1 &&
+ bits->height == 1)
+ {
+@@ -4322,7 +4429,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbC
+ {
+ fetchMask = (scanFetchProc)fbFetchExternalAlpha;
+ }
+- else if (bits->common.repeat == PIXMAN_REPEAT_NORMAL &&
++ else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
+ bits->width == 1 && bits->height == 1)
+ {
+ fetchMask = (scanFetchProc)fbFetchSolid;
diff --git a/x11/pixman/patches/patch-ab b/x11/pixman/patches/patch-ab
new file mode 100644
index 00000000000..956846ecda8
--- /dev/null
+++ b/x11/pixman/patches/patch-ab
@@ -0,0 +1,13 @@
+$NetBSD: patch-ab,v 1.3 2008/02/18 05:36:51 bjs Exp $
+
+--- pixman/pixman-private.h.orig 2008-02-18 00:32:50.000000000 -0500
++++ pixman/pixman-private.h
+@@ -600,6 +600,8 @@ union pixman_image
+ #define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) : \
+ ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
+
++#define CLIP(a,b,c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a)))
++
+ #if 0
+ /* FIXME: the MOD macro above is equivalent, but faster I think */
+ #define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))