[cairo] EXTEND_PAD Support

Jeff Muizelaar jeff at infidigm.net
Sun Dec 30 14:41:58 PST 2007


On Sun, Dec 30, 2007 at 04:50:29AM -0500, Antoine Azar wrote:
> Hey all,
> 
> I'm starting work on implementing extend_pad support. I think Carl 
> started having a look, any pointers will be appreciated.
> 

I'm not sure how much you've done but here's an untested implementation
that I've done. I haven't checked whether cairo needs any modification
for this to work either...

The basic idea should be the same as EXTEND_REPEAT but using a
saturating CLIP() instead of MOD(). Note, the resulting code adds lots
of duplication, but the code was already duplicated before :)

-Jeff
-------------- next part --------------
commit 7f70cafa11aac1e073bd0da1ad9474ad6972b165
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sun Dec 30 17:36:31 2007 -0500

    Add support for EXTEND_PAD.

diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c
index 1e91864..1d5d1cc 100644
--- a/pixman/pixman-compose.c
+++ b/pixman/pixman-compose.c
@@ -3650,6 +3650,55 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                     v.vector[2] += unit.vector[2];
                 }
             }
+        } else if (pict->common.repeat == PIXMAN_REPEAT_PAD) {
+            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 = CLIP(DIV(v.vector[1],v.vector[2]), 0, pict->height);
+				x = CLIP(DIV(v.vector[0],v.vector[2]), 0, pict->width);
+			    } else {
+				y = CLIP(v.vector[1]>>16, 0, pict->height);
+				x = CLIP(v.vector[0]>>16, 0, pict->width);
+			    }
+			    *(buffer + i) = fetch((pixman_image_t *)pict, bits + y * stride, x, indexed);
+			}
+		    }
+		    
+                    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 = CLIP(DIV(v.vector[1],v.vector[2]), 0, pict->height);
+				x = CLIP(DIV(v.vector[0],v.vector[2]), 0, pict->width);
+			    } else {
+				y = CLIP(v.vector[1]>>16, 0, pict->height);
+				x = CLIP(v.vector[0]>>16, 0, pict->width);
+			    }
+			    if (pixman_region_contains_point (pict->common.src_clip, x, y, &box))
+				*(buffer + i) = fetch ((pixman_image_t *)pict, bits + y*stride, x, indexed);
+			    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;
@@ -3845,7 +3894,143 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                     v.vector[2] += unit.vector[2];
                 }
             }
-        } else {
+        } else if (pict->common.repeat == PIXMAN_REPEAT_PAD) {
+            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 *b;
+			    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);
+			    x2 = CLIP (x2, 0, pict->width);
+			    y1 = CLIP (y1, 0, pict->height);
+			    y2 = CLIP (y2, 0, pict->height);
+			    
+			    b = bits + y1*stride;
+			    
+			    tl = fetch((pixman_image_t *)pict, b, x1, indexed);
+			    tr = fetch((pixman_image_t *)pict, b, x2, indexed);
+			    b = bits + y2*stride;
+			    bl = fetch((pixman_image_t *)pict, b, x1, indexed);
+			    br = fetch((pixman_image_t *)pict, b, x2, indexed);
+			    
+			    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 *b;
+			    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);
+			    x2 = CLIP (x2, 0, pict->width);
+			    y1 = CLIP (y1, 0, pict->height);
+			    y2 = CLIP (y2, 0, pict->height);
+			    
+			    b = bits + y1*stride;
+			    
+			    tl = pixman_region_contains_point(pict->common.src_clip, x1, y1, &box)
+				? fetch((pixman_image_t *)pict, b, x1, indexed) : 0;
+			    tr = pixman_region_contains_point(pict->common.src_clip, x2, y1, &box)
+				? fetch((pixman_image_t *)pict, b, x2, indexed) : 0;
+			    b = bits + (y2)*stride;
+			    bl = pixman_region_contains_point(pict->common.src_clip, x1, y2, &box)
+				? fetch((pixman_image_t *)pict, b, x1, indexed) : 0;
+			    br = pixman_region_contains_point(pict->common.src_clip, x2, y2, &box)
+				? fetch((pixman_image_t *)pict, b, x2, indexed) : 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) {
@@ -4014,10 +4199,30 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
 		    srtot = sgtot = sbtot = satot = 0;
 		    
 		    for (y = y1; y < y2; y++) {
-			int ty = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (y, pict->height) : 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);
+				break;
+			    default:
+				ty = y;
+			}
 			for (x = x1; x < x2; x++) {
 			    if (*p) {
-				int tx = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (x, pict->width) : x;
+				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);
+					break;
+				    default:
+					tx = x;
+				}
 				if (pixman_region_contains_point (pict->common.src_clip, tx, ty, &box)) {
 				    uint32_t *b = bits + (ty)*stride;
 				    uint32_t c = fetch((pixman_image_t *)pict, b, tx, indexed);
@@ -4183,7 +4388,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 	{
 	    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)
 	{
@@ -4221,7 +4426,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 	    {
 		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/pixman/pixman-private.h b/pixman/pixman-private.h
index 6487bfd..8d71c56 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -585,6 +585,8 @@ union pixman_image
 
 #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
 
+#define CLIP(a,b,c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a)))
+
 #define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :		\
 		  ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
 


More information about the cairo mailing list