[cairo] patches for pixman

Klaus Stehle klaus.stehle at uni-tuebingen.de
Wed Dec 13 01:50:59 PST 2006


I have some patches for libpixman. These patches were originally thought
to make support of special formats like 24bpp-RGB24 possible, and while
I was thinking of throwing them away, I found that the patches might be
helpful for a format like CAIRO_FORMAT_A8.

Here is a short example which prints the picture of the letter "A" to
the text console:


//----------%<----------%<----------%<----------%<----------%<----------

#include <cairo.h>
#include <stdio.h>

#define wd (50)
#define ht (25)

unsigned char buffer[wd*ht];

int main ()
{
    cairo_surface_t *sfc;
    cairo_t *cg;
    int x, y;

    sfc = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8, wd, ht, wd);
    cg = cairo_create (sfc);
    cairo_set_source_rgba (cg, 0, 0, 0, 1.0);
    cairo_set_font_size (cg, 25.0);
    cairo_move_to (cg, 2, 20);
    cairo_show_text (cg, "A");
    cairo_stroke (cg);

    for (y=0; y<ht; y++) {
	for (x=0; x<wd; x++)
	    putchar (buffer[y*wd+x] ? '*' : '.');
	putchar('\n');
    }
    return 0;
}

//----------%<----------%<----------%<----------%<----------%<----------


The output is sheared and slanted. The letter "A" is not very nice.
If you change the value of 'wd' to 52, everything will work fine.

There is a bug in pixman. The core of the bug is the macro fbGetDrawable
in pixman/src/pixman-xserver-compat.h which divides the value of 'stride'
by 4, to make address calculations with (unsigned*) pointers possible.
This method fails in all cases where stride is not a multiple of 4.

These patches try to simplify the address calculations.
They also fix bug #7437.

But they aren't complete. Possibly more appearances of the macro
fbGetDrawable should be replaced ...

Perhaps the patches are too much. To fix bug #7437 and the problem shown
above the patches 0001--0003 would suffice.


cheers
Klaus
-------------- next part --------------
From cba08e8734c3ae9a4e4ba878df6d1e6a80581a11 Mon Sep 17 00:00:00 2001
From: Klaus Stehle <klaus.stehle at uni-tuebingen.de>
Date: Fri, 1 Dec 2006 20:19:18 +0100
Subject: [PATCH] Three new macros to replace fbGetDrawable.

pixman/src/pixman-xserver-compat.h:
A new macro fbGetDrawableS has been added as replacement for
fbGetDrawable, and this new macro returns the correct value of
stride in number of bytes. The values xoff and yoff, which are
always set to zero by fbGetDrawable are thrown away.
A new macro fbAddrAdd adds an offset expressed as number of
bytes to a pointer of any type and returns the result.
A new macro fbInPlaceAdd does the same addition in place.
---
 pixman/src/pixman-xserver-compat.h |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/pixman/src/pixman-xserver-compat.h b/pixman/src/pixman-xserver-compat.h
index a09367d..073e733 100644
--- a/pixman/src/pixman-xserver-compat.h
+++ b/pixman/src/pixman-xserver-compat.h
@@ -86,6 +86,25 @@ typedef pixman_triangle_t	xTriangle;
     (yoff) = 0; \
 }
 
+/* The macro above is only working correct with 32 bpp formats.
+ * Used with other formats it may not return the correct value of stride.
+ * Here is a new fbGetDrawableS macro without the evil integer division.
+ * The value of stride will always be expressed as number of bytes */
+#define fbGetDrawableS(pDrawable, buf, outstride, outbpp) { \
+    (buf) = (pDrawable)->data; \
+    (outstride) = ((int) pDrawable->stride); \
+    (outbpp) = (pDrawable)->bpp; \
+}
+
+/* Add an offset (number of bytes) to a pointer of any type. */
+#define fbAddrAdd(type, buffer, offset) \
+    ((type *)(((char *)(buffer)) + (offset)))
+
+/* Add an offset (number of bytes) to a pointer of any type in place. */
+#define fbInPlaceAdd(type, buffer, offset) \
+    ((buffer) = (type *)(((char *)(buffer)) + (offset)))
+
+
 /* Extended repeat attributes included in 0.10 */
 #define RepeatNone                          0
 #define RepeatNormal                        1
-- 
1.4.4

-------------- next part --------------
From f8f2607bd47fda69d02ef5297afd46f0994ce38d Mon Sep 17 00:00:00 2001
From: Klaus Stehle <klaus.stehle at uni-tuebingen.de>
Date: Fri, 1 Dec 2006 20:30:34 +0100
Subject: [PATCH] Replace fbGetDrawable in fbcompose.c

pixman/src/fbcompose.c:
Replaced fbGetDrawable in fbFetchSolid.
Replaced fbGetDrawable in fbFetch.
Replaced fbGetDrawable in fbStore.
Replaced fbGetDrawable twice in fbStoreExternalAlpha.
Not replaced old macro is still in fbFetchTransformed
and fbCompositeRect -- that must be done later ...
---
 pixman/src/fbcompose.c |   32 ++++++++++----------------------
 1 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 4958241..5b0373f 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -2686,7 +2686,6 @@ static void fbFetchSolid(PicturePtr pict
     FbBits *bits;
     FbStride stride;
     int bpp;
-    int xoff, yoff;
     CARD32 color;
     CARD32 *end;
     fetchPixelProc fetch = fetchPixelProcForPicture(pict);
@@ -2696,8 +2695,7 @@ static void fbFetchSolid(PicturePtr pict
     miIndexedPtr indexed = NULL;
 #endif
 
-    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
-    bits += yoff*stride + (xoff*bpp >> FB_SHIFT);
+    fbGetDrawableS (pict->pDrawable, bits, stride, bpp);
 
     color = fetch(bits, 0, indexed);
 
@@ -2711,7 +2709,6 @@ static void fbFetch(PicturePtr pict, int
     FbBits *bits;
     FbStride stride;
     int bpp;
-    int xoff, yoff;
     fetchProc fetch = fetchProcForPicture(pict);
 #ifdef PIXMAN_INDEXED_FORMATS
     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
@@ -2719,11 +2716,9 @@ static void fbFetch(PicturePtr pict, int
     miIndexedPtr indexed = NULL;
 #endif
 
-    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
-    x += xoff;
-    y += yoff;
+    fbGetDrawableS (pict->pDrawable, bits, stride, bpp);
 
-    bits += y*stride;
+    fbInPlaceAdd (FbBits, bits, y*stride);
 
     fetch(bits, x, width, buffer, indexed);
 }
@@ -3571,7 +3566,6 @@ static void fbStore(PicturePtr pict, int
     FbBits *bits;
     FbStride stride;
     int bpp;
-    int xoff, yoff;
     storeProc store = storeProcForPicture(pict);
 #ifdef PIXMAN_INDEXED_FORMATS
     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
@@ -3579,11 +3573,10 @@ static void fbStore(PicturePtr pict, int
     miIndexedPtr indexed = NULL;
 #endif
 
-    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
-    x += xoff;
-    y += yoff;
+    fbGetDrawableS (pict->pDrawable, bits, stride, bpp);
+
+    fbInPlaceAdd (FbBits, bits, y*stride);
 
-    bits += y*stride;
     store(bits, buffer, x, width, indexed);
 }
 
@@ -3592,7 +3585,6 @@ static void fbStoreExternalAlpha(Picture
     FbBits *bits, *alpha_bits;
     FbStride stride, astride;
     int bpp, abpp;
-    int xoff, yoff;
     int ax, ay;
     storeProc store;
     storeProc astore;
@@ -3619,15 +3611,11 @@ static void fbStoreExternalAlpha(Picture
     ax = x;
     ay = y;
 
-    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
-    x += xoff;
-    y += yoff;
-    fbGetDrawable (pict->alphaMap->pDrawable, alpha_bits, astride, abpp, xoff, yoff);
-    ax += xoff;
-    ay += yoff;
+    fbGetDrawableS (pict->pDrawable, bits, stride, bpp);
+    fbGetDrawableS (pict->alphaMap->pDrawable, alpha_bits, astride, abpp);
 
-    bits       += y*stride;
-    alpha_bits += (ay - pict->alphaOrigin.y)*astride;
+    fbInPlaceAdd (FbBits, bits, y*stride);
+    fbInPlaceAdd (FbBits, alpha_bits, (ay - pict->alphaOrigin.y)*astride);
 
     store(bits, buffer, x, width, indexed);
     astore(alpha_bits, buffer, ax - pict->alphaOrigin.x, width, aindexed);
-- 
1.4.4

-------------- next part --------------
From 4b9eefa05e96afc4bf9fb733e9b720cff6adc921 Mon Sep 17 00:00:00 2001
From: Klaus Stehle <klaus.stehle at uni-tuebingen.de>
Date: Wed, 22 Nov 2006 22:17:36 +0100
Subject: [PATCH] Replaced fbGetDrawable in fbComposeGetStart.

pixman/src/fbpict.h:
Replaced fbGetDrawable in fbComposeGetStart.
---
 pixman/src/fbpict.h |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/pixman/src/fbpict.h b/pixman/src/fbpict.h
index 0ff0c11..309c3ab 100644
--- a/pixman/src/fbpict.h
+++ b/pixman/src/fbpict.h
@@ -110,11 +110,11 @@
     FbBits	*__bits__; \
     FbStride	__stride__; \
     int		__bpp__; \
-    int		__xoff__,__yoff__; \
 \
-    fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
-    (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \
-    (line) = ((type *) __bits__) + (stride) * ((y) + __yoff__) + (mul) * ((x) + __xoff__); \
+    fbGetDrawableS((pict)->pDrawable,__bits__,__stride__,__bpp__); \
+    (stride) = __stride__ * sizeof(FbBits) \
+               / sizeof(pixman_bits_t) / sizeof(type); \
+    (line) = ((type *) __bits__) + (stride) * (y) + (mul) * (x); \
 }
 
 #define cvt8888to0565(s)    ((((s) >> 3) & 0x001f) | \
-- 
1.4.4

-------------- next part --------------
From 4d6f46f9153427a56148db4fc8f3d3879a64875d Mon Sep 17 00:00:00 2001
From: Klaus Stehle <klaus.stehle at uni-tuebingen.de>
Date: Fri, 1 Dec 2006 21:49:58 +0100
Subject: [PATCH] fbGetDrawable also replaced in fbFetchTransformed.

pixman/src/fbcompose.c:
Replaced fbGetDrawable in fbFetchTransformed.
Not replaced old macro is still fbCompositeRect --
that must be done later ...
---
 pixman/src/fbcompose.c |   31 ++++++++++++++-----------------
 1 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 5b0373f..5fa86d6 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -3046,7 +3046,6 @@ static void fbFetchTransformed(PicturePt
     FbBits     *bits;
     FbStride    stride;
     int         bpp;
-    int         xoff, yoff;
     fetchPixelProc   fetch;
     PictVector	v;
     PictVector  unit;
@@ -3061,9 +3060,7 @@ static void fbFetchTransformed(PicturePt
 
     fetch = fetchPixelProcForPicture(pict);
 
-    fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff);
-    x += xoff;
-    y += yoff;
+    fbGetDrawableS (pict->pDrawable, bits, stride, bpp);
 
     /* reference point is the center of the pixel */
     v.vector[0] = IntToxFixed(x) + xFixed1/2;
@@ -3102,7 +3099,7 @@ static void fbFetchTransformed(PicturePt
 				y = MOD(v.vector[1]>>16, pict->pDrawable->height);
 				x = MOD(v.vector[0]>>16, pict->pDrawable->width);
 			    }
-			    buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+			    buffer[i] = fetch (fbAddrAdd (FbBits, bits, (y + pict->pDrawable->y)*stride), x + pict->pDrawable->x, indexed);
 			}
 		    }
                     v.vector[0] += unit.vector[0];
@@ -3124,7 +3121,7 @@ static void fbFetchTransformed(PicturePt
 				x = MOD(v.vector[0]>>16, pict->pDrawable->width);
 			    }
 			    if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
-				buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+				buffer[i] = fetch (fbAddrAdd (FbBits, bits, (y + pict->pDrawable->y)*stride), x + pict->pDrawable->x, indexed);
 			    else
 				buffer[i] = 0;
 			}
@@ -3151,7 +3148,7 @@ static void fbFetchTransformed(PicturePt
 				x = v.vector[0]>>16;
 			    }
 			    buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
-				0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+				0 : fetch (fbAddrAdd (FbBits, bits, (y + pict->pDrawable->y)*stride), x + pict->pDrawable->x, indexed);
 			}
 		    }
                     v.vector[0] += unit.vector[0];
@@ -3171,7 +3168,7 @@ static void fbFetchTransformed(PicturePt
                             x = v.vector[0]>>16;
                         }
                         if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
-                            buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+                            buffer[i] = fetch (fbAddrAdd (FbBits, bits, (y + pict->pDrawable->y)*stride), x + pict->pDrawable->x, indexed);
                         else
                             buffer[i] = 0;
                     }
@@ -3227,11 +3224,11 @@ static void fbFetchTransformed(PicturePt
 			    y1 = MOD (y1, pict->pDrawable->height);
 			    y2 = MOD (y2, pict->pDrawable->height);
 
-			    b = bits + (y1 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y1 + pict->pDrawable->y)*stride);
 
 			    tl = fetch(b, x1 + pict->pDrawable->x, indexed);
 			    tr = fetch(b, x2 + pict->pDrawable->x, indexed);
-			    b = bits + (y2 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y2 + pict->pDrawable->y)*stride);
 			    bl = fetch(b, x1 + pict->pDrawable->x, indexed);
 			    br = fetch(b, x2 + pict->pDrawable->x, indexed);
 
@@ -3291,13 +3288,13 @@ static void fbFetchTransformed(PicturePt
 			    y1 = MOD (y1, pict->pDrawable->height);
 			    y2 = MOD (y2, pict->pDrawable->height);
 
-			    b = bits + (y1 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y1 + pict->pDrawable->y)*stride);
 
 			    tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
 				? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
 			    tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
 				? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
-			    b = bits + (y2 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y2 + pict->pDrawable->y)*stride);
 			    bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
 				? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
 			    br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
@@ -3358,7 +3355,7 @@ static void fbFetchTransformed(PicturePt
 			    idistx = 256 - distx;
 			    idisty = 256 - disty;
 
-			    b = bits + (y1 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y1 + pict->pDrawable->y)*stride);
 			    x_off = x1 + pict->pDrawable->x;
 
 			    x1_out = (x1 < box.x1) | (x1 >= box.x2);
@@ -3368,7 +3365,7 @@ static void fbFetchTransformed(PicturePt
 
 			    tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed);
 			    tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed);
-			    b += stride;
+			    fbInPlaceAdd (FbBits, b, stride);
 			    bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
 			    br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
 
@@ -3423,14 +3420,14 @@ static void fbFetchTransformed(PicturePt
 			    idistx = 256 - distx;
 			    idisty = 256 - disty;
 
-			    b = bits + (y1 + pict->pDrawable->y)*stride;
+			    b = fbAddrAdd (FbBits, bits, (y1 + pict->pDrawable->y)*stride);
 			    x_off = x1 + pict->pDrawable->x;
 
 			    tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
 				? fetch(b, x_off, indexed) : 0;
 			    tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
 				? fetch(b, x_off + 1, indexed) : 0;
-			    b += stride;
+			    fbInPlaceAdd (FbBits, b, stride);
 			    bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
 				? fetch(b, x_off, indexed) : 0;
 			    br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
@@ -3496,7 +3493,7 @@ static void fbFetchTransformed(PicturePt
 			    if (*p) {
 				int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
 				if (pixman_region_contains_point (pict->pSourceClip, tx, ty, &box)) {
-				    FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
+				    FbBits *b = fbAddrAdd (FbBits, bits, (ty + pict->pDrawable->y)*stride);
 				    CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
 
 				    srtot += Red(c) * *p;
-- 
1.4.4

-------------- next part --------------
From 0e34a5762967c39b1b87a5451a4382bd2e934e8f Mon Sep 17 00:00:00 2001
From: Klaus Stehle <klaus.stehle at uni-tuebingen.de>
Date: Mon, 4 Dec 2006 20:51:49 +0100
Subject: [PATCH] fbGetDrawable also replaced in fbCompositeRect.

pixman/src/fbcompose.c:
Replaced fbGetDrawable in fbCompositeRect.
---
 pixman/src/fbcompose.c |   18 ++++++++----------
 1 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 5fa86d6..5ba04e0 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -3633,7 +3633,7 @@ fbCompositeRect (const FbComposeData *da
     unsigned int maskClass = SourcePictClassUnknown;
     FbBits *bits = NULL;    /* squelch bogus compiler warning */
     FbStride stride = 0;    /* squelch bogus compiler warning */
-    int	xoff = 0, yoff = 0; /* squelch bogus compiler warning */
+    int	bpp = 0;            /* squelch bogus compiler warning */
 
     if (data->op == PIXMAN_OPERATOR_CLEAR)
         fetchSrc = NULL;
@@ -3723,11 +3723,7 @@ fbCompositeRect (const FbComposeData *da
     }
 
     if (!store)
-    {
-	int bpp;
-
-	fbGetDrawable (data->dest->pDrawable, bits, stride, bpp, xoff, yoff);
-    }
+	fbGetDrawableS (data->dest->pDrawable, bits, stride, bpp);
 
     if (fetchSrc		   &&
 	fetchMask		   &&
@@ -3791,8 +3787,9 @@ fbCompositeRect (const FbComposeData *da
 	    else
 	    {
 		/* blend */
-		compose (bits + (data->yDest + i+ yoff) * stride +
-			 data->xDest + xoff,
+	        compose (fbAddrAdd (FbBits, bits,
+				    (data->yDest + i) * stride +
+				    data->xDest * bpp / 8),
 			 src_buffer, mask_buffer, data->width);
 	    }
 	}
@@ -3879,8 +3876,9 @@ fbCompositeRect (const FbComposeData *da
 	    else
 	    {
 		/* blend */
-		compose (bits + (data->yDest + i+ yoff) * stride +
-			 data->xDest + xoff,
+	        compose (fbAddrAdd (FbBits, bits,
+				    (data->yDest + i) * stride +
+				    data->xDest * bpp / 8),
 			 src_mask_buffer, data->width);
 	    }
 	}
-- 
1.4.4



More information about the cairo mailing list