Keith Packard <[EMAIL PROTECTED]> writes:

> Around 18 o'clock on Aug 1, Bradley T Hughes wrote:
> 
> > I have kept the code in qpainter_x11.cpp as is, using XRender* calls 
> > directly.  Clipping and such things are working now, so why break them, 
> > right? :)
> 
> Please don't use XRender calls directly -- that means Xft2 won't be usable
> on servers which don't support Render.  I can export an
> XftDrawSetClipRectangles call if you like; the alternative is to simply
> construct an X region from your list of X rectangles and use the existing
> XftDrawSetClip call.

Here's a patch to add XftDrawSetClipRectangles that I had sitting
around (did it when coming back from Boston).

I'm of slightly mixed feelings about this addition:

 - Having two interfaces to do the same thing is always ugly.
 - Converting to a Region and back probably doesn't affect
   speed significantly cases much if reasonably clipping shapes 
   are used. 

But:

 - Repeatedly calling XUnionRectWithRegion is algorithmically
   very inefficient.

The 'ordering' parameter probably could be omitted; I put it in since
(for the non-Render case) it saves the server the work when
reconstructing the region. (The interesting case for me, as presumably
for Qt, involves a set of YXBanded rectangles.)

Regards,
                                        Owen

--- fcpackage.02-07-13.12-22/Xft/xftdraw.c.cliprects	Mon Jul 22 09:44:00 2002
+++ fcpackage.02-07-13.12-22/Xft/xftdraw.c	Mon Jul 22 11:29:17 2002
@@ -153,7 +153,8 @@
     draw->render.pict = 0;
     draw->core.gc = 0;
     draw->core.use_pixmap = 0;
-    draw->clip = 0;
+    draw->have_clip_rects = False;
+    draw->clip.region = 0;
     draw->subwindow_mode = ClipByChildren;
     XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
     return draw;
@@ -177,7 +178,8 @@
     draw->colormap = 0;
     draw->render.pict = 0;
     draw->core.gc = 0;
-    draw->clip = 0;
+    draw->have_clip_rects = False;
+    draw->clip.region = 0;
     draw->subwindow_mode = ClipByChildren;
     XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
     return draw;
@@ -202,7 +204,8 @@
     draw->colormap = 0;
     draw->render.pict = 0;
     draw->core.gc = 0;
-    draw->clip = 0;
+    draw->have_clip_rects = False;
+    draw->clip.region = 0;
     draw->subwindow_mode = ClipByChildren;
     XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
     return draw;
@@ -284,8 +287,16 @@
 	XRenderFreePicture (draw->dpy, draw->render.pict);
     if (draw->core.gc)
 	XFreeGC (draw->dpy, draw->core.gc);
-    if (draw->clip)
-	XDestroyRegion (draw->clip);
+    if (draw->have_clip_rects)
+    {
+	if (draw->clip.rects.r)
+	    XFree (draw->clip.rects.r);
+    }
+    else
+    {
+	if (draw->clip.region)
+	    XDestroyRegion (draw->clip.region);
+    }
     XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw));
     free (draw);
 }
@@ -398,9 +409,18 @@
 						  format, mask, &pa);
 	if (!draw->render.pict)
 	    return FcFalse;
-	if (draw->clip)
-	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
-					 draw->clip);
+	if (draw->have_clip_rects)
+	{
+	    XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
+					     draw->clip.rects.xOrigin, draw->clip.rects.yOrigin,
+					     draw->clip.rects.r, draw->clip.rects.n);
+	}
+	else
+	{
+	    if (draw->clip.region)
+		XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
+					     draw->clip.region);
+	}
     }
     return FcTrue;
 }
@@ -420,8 +440,17 @@
 	draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv);
 	if (!draw->core.gc)
 	    return FcFalse;
-	if (draw->clip)
-	    XSetRegion (draw->dpy, draw->core.gc, draw->clip);
+	if (draw->have_clip_rects)
+	{
+	    XSetClipRectangles (draw->dpy, draw->core.gc,
+				draw->clip.rects.xOrigin, draw->clip.rects.yOrigin,
+				draw->clip.rects.r, draw->clip.rects.n, draw->clip.rects.ordering);
+	}
+	else
+	{
+	    if (draw->clip.region)
+		XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
+	}
     }
     XSetForeground (draw->dpy, draw->core.gc, color->pixel);
     return FcTrue;
@@ -739,16 +768,79 @@
 }
 
 Bool
+XftDrawSetClipRectangles(XftDraw            *draw,
+			 int                 xOrigin,
+			 int                 yOrigin,
+			 _Xconst XRectangle *rects,
+			 int		     n,
+			 int                 ordering)
+{
+    XRectangle *new;
+    
+    if (draw->have_clip_rects &&
+	n == draw->clip.rects.n &&
+	memcmp (draw->clip.rects.r, rects, n * sizeof (XRectangle)) == 0)
+	return True;
+    
+    if (n)
+    {
+	new = (XRectangle *) malloc (n * sizeof (XRectangle));
+	if (!new)
+	    return False;
+	
+	memcpy (new, rects, n * sizeof (XRectangle));
+    }
+    else
+    {
+	new = 0;
+    }
+
+    if (draw->have_clip_rects)
+    {
+	if (draw->clip.rects.r)
+	    XFree (draw->clip.rects.r);
+    }
+    else if (!draw->have_clip_rects && draw->clip.region)
+    {
+	if (draw->clip.region)
+	    XDestroyRegion (draw->clip.region);
+	draw->have_clip_rects = True;
+    }
+
+    draw->have_clip_rects = True;
+    draw->clip.rects.r = new;
+    draw->clip.rects.n = n;
+    draw->clip.rects.xOrigin = xOrigin;
+    draw->clip.rects.yOrigin = yOrigin;
+    draw->clip.rects.ordering = ordering;
+    
+    if (draw->render.pict)
+    {
+	XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict, xOrigin, yOrigin, rects, n);
+    }
+    if (draw->core.gc)
+    {
+	XSetClipRectangles (draw->dpy, draw->core.gc, xOrigin, yOrigin,
+			    draw->clip.rects.r, n, ordering);
+    }
+
+    return True;
+}
+
+Bool
 XftDrawSetClip (XftDraw	*draw,
 		Region	r)
 {
     Region			n = 0;
 
-    if (!r && !draw->clip)
-	return True;
-
-    if (r && draw->clip && XEqualRegion (r, draw->clip))
-	return True;
+    if (!draw->have_clip_rects)
+    {
+	if (!r && !draw->clip.region)
+	    return True;
+	
+	if (r && draw->clip.region && XEqualRegion (r, draw->clip.region))
+	    return True;
+    }
 
     if (r)
     {
@@ -761,10 +853,25 @@
 		return False;
 	    }
 	}
+	else
+	    return False;
+    }
+
+    if (draw->have_clip_rects)
+    {
+	if (draw->clip.rects.r)
+	    XFree (draw->clip.rects.r);
+
+	draw->have_clip_rects = False;
     }
-    if (draw->clip)
-	XDestroyRegion (draw->clip);
-    draw->clip = n;
+    else
+    {
+	if (draw->clip.region)
+	    XDestroyRegion (draw->clip.region);
+    }
+    
+    draw->clip.region = n;
+    
     if (draw->render.pict)
     {
 	if (n)
@@ -780,7 +887,7 @@
     if (draw->core.gc)
     {
 	if (n)
-	    XSetRegion (draw->dpy, draw->core.gc, draw->clip);
+	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
 	else
 	    XSetClipMask (draw->dpy, draw->core.gc, None);
     }
--- fcpackage.02-07-13.12-22/Xft/xftint.h.cliprects	Mon Jul 22 10:03:41 2002
+++ fcpackage.02-07-13.12-22/Xft/xftint.h	Mon Jul 22 10:12:27 2002
@@ -162,7 +162,17 @@
     Drawable	    drawable;
     Visual	    *visual;	/* NULL for bitmaps */
     Colormap	    colormap;
-    Region	    clip;
+    Bool            have_clip_rects;
+    union {
+	Region	    region;
+	struct {
+	    XRectangle *r;
+	    int         n;
+	    int         xOrigin;
+	    int         yOrigin;
+	    int         ordering;
+	} rects;
+    } clip;
     int		    subwindow_mode;
     struct {
 	Picture		pict;
--- fcpackage.02-07-13.12-22/Xft/Xft.h.cliprects	Mon Jul 22 11:03:03 2002
+++ fcpackage.02-07-13.12-22/Xft/Xft.h	Mon Jul 22 11:05:14 2002
@@ -262,6 +262,14 @@
 
 
 Bool
+XftDrawSetClipRectangles(XftDraw            *draw,
+			 int                 xOrigin,
+			 int                 yOrigin,
+			 _Xconst XRectangle *rects,
+			 int		     n,
+			 int                 ordering);
+
+Bool
 XftDrawSetClip (XftDraw	    *d,
 		Region	    r);
 

Reply via email to