xftdraw.c revision 8292847c
1c76ae52dSmrg/*
2c76ae52dSmrg * Copyright © 2000 Keith Packard
3c76ae52dSmrg *
4c76ae52dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
5c76ae52dSmrg * documentation for any purpose is hereby granted without fee, provided that
6c76ae52dSmrg * the above copyright notice appear in all copies and that both that
7c76ae52dSmrg * copyright notice and this permission notice appear in supporting
8c76ae52dSmrg * documentation, and that the name of Keith Packard not be used in
9c76ae52dSmrg * advertising or publicity pertaining to distribution of the software without
10c76ae52dSmrg * specific, written prior permission.  Keith Packard makes no
11c76ae52dSmrg * representations about the suitability of this software for any purpose.  It
12c76ae52dSmrg * is provided "as is" without express or implied warranty.
13c76ae52dSmrg *
14c76ae52dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15c76ae52dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16c76ae52dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17c76ae52dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18c76ae52dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19c76ae52dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20c76ae52dSmrg * PERFORMANCE OF THIS SOFTWARE.
21c76ae52dSmrg */
22c76ae52dSmrg
23c76ae52dSmrg#include "xftint.h"
24c76ae52dSmrg
25c76ae52dSmrg/*
26c76ae52dSmrg * Ok, this is a pain.  To share source pictures across multiple destinations,
27c76ae52dSmrg * the screen for each drawable must be discovered.
28c76ae52dSmrg */
29c76ae52dSmrg
30c76ae52dSmrgstatic int
31c76ae52dSmrg_XftDrawScreen (Display *dpy, Drawable drawable, Visual *visual)
32c76ae52dSmrg{
33c76ae52dSmrg    int		    s;
34c76ae52dSmrg    Window	    root;
35c76ae52dSmrg    int		    x, y;
36c76ae52dSmrg    unsigned int    width, height, borderWidth, depth;
37c76ae52dSmrg    /* Special case the most common environment */
38c76ae52dSmrg    if (ScreenCount (dpy) == 1)
39c76ae52dSmrg	return 0;
40c76ae52dSmrg    /*
41c76ae52dSmrg     * If we've got a visual, look for the screen that points at it.
42c76ae52dSmrg     * This requires no round trip.
43c76ae52dSmrg     */
44c76ae52dSmrg    if (visual)
45c76ae52dSmrg    {
46c76ae52dSmrg	for (s = 0; s < ScreenCount (dpy); s++)
47c76ae52dSmrg	{
48c76ae52dSmrg	    XVisualInfo	template, *ret;
49c76ae52dSmrg	    int		nret;
50c76ae52dSmrg
51c76ae52dSmrg	    template.visualid = visual->visualid;
52c76ae52dSmrg	    template.screen = s;
53c76ae52dSmrg	    ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask,
54c76ae52dSmrg				  &template, &nret);
55c76ae52dSmrg	    if (ret)
56c76ae52dSmrg	    {
57c76ae52dSmrg		XFree (ret);
58c76ae52dSmrg		return s;
59c76ae52dSmrg	    }
60c76ae52dSmrg	}
61c76ae52dSmrg    }
62c76ae52dSmrg    /*
63c76ae52dSmrg     * Otherwise, as the server for the drawable geometry and find
64c76ae52dSmrg     * the screen from the root window.
65c76ae52dSmrg     * This takes a round trip.
66c76ae52dSmrg     */
67c76ae52dSmrg    if (XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height,
68c76ae52dSmrg		      &borderWidth, &depth))
69c76ae52dSmrg    {
70c76ae52dSmrg	for (s = 0; s < ScreenCount (dpy); s++)
71c76ae52dSmrg	{
72c76ae52dSmrg	    if (RootWindow (dpy, s) == root)
73c76ae52dSmrg		return s;
74c76ae52dSmrg	}
75c76ae52dSmrg    }
76c76ae52dSmrg    /*
77c76ae52dSmrg     * Make a guess -- it's probably wrong, but then the app probably
78c76ae52dSmrg     * handed us a bogus drawable in this case
79c76ae52dSmrg     */
80c76ae52dSmrg    return 0;
81c76ae52dSmrg}
82c76ae52dSmrg
83c76ae52dSmrg_X_HIDDEN unsigned int
84c76ae52dSmrgXftDrawDepth (XftDraw *draw)
85c76ae52dSmrg{
86c76ae52dSmrg    if (!draw->depth)
87c76ae52dSmrg    {
88c76ae52dSmrg	Window		    root;
89c76ae52dSmrg	int		    x, y;
90c76ae52dSmrg	unsigned int	    width, height, borderWidth, depth;
912836776bSmrg	if (XGetGeometry (draw->dpy, draw->drawable,
92c76ae52dSmrg			  &root, &x, &y, &width, &height,
93c76ae52dSmrg			  &borderWidth, &depth))
94c76ae52dSmrg	    draw->depth = depth;
95c76ae52dSmrg    }
96c76ae52dSmrg    return draw->depth;
97c76ae52dSmrg}
98c76ae52dSmrg
99c76ae52dSmrg_X_HIDDEN unsigned int
100c76ae52dSmrgXftDrawBitsPerPixel (XftDraw	*draw)
101c76ae52dSmrg{
102c76ae52dSmrg    if (!draw->bits_per_pixel)
103c76ae52dSmrg    {
104c76ae52dSmrg	XPixmapFormatValues *formats;
105c76ae52dSmrg	int		    nformats;
106c76ae52dSmrg	unsigned int	    depth;
1072836776bSmrg
108c76ae52dSmrg	if ((depth = XftDrawDepth (draw)) &&
109c76ae52dSmrg	    (formats = XListPixmapFormats (draw->dpy, &nformats)))
110c76ae52dSmrg	{
111c76ae52dSmrg	    int	i;
112c76ae52dSmrg
113c76ae52dSmrg	    for (i = 0; i < nformats; i++)
114c76ae52dSmrg	    {
115c76ae52dSmrg		if (formats[i].depth == depth)
116c76ae52dSmrg		{
117c76ae52dSmrg		    draw->bits_per_pixel = formats[i].bits_per_pixel;
118c76ae52dSmrg		    break;
119c76ae52dSmrg		}
120c76ae52dSmrg	    }
121c76ae52dSmrg	    XFree (formats);
122c76ae52dSmrg	}
123c76ae52dSmrg    }
124c76ae52dSmrg    return draw->bits_per_pixel;
125c76ae52dSmrg}
126c76ae52dSmrg
127c76ae52dSmrg_X_EXPORT XftDraw *
128c76ae52dSmrgXftDrawCreate (Display   *dpy,
129c76ae52dSmrg	       Drawable  drawable,
130c76ae52dSmrg	       Visual    *visual,
131c76ae52dSmrg	       Colormap  colormap)
132c76ae52dSmrg{
133c76ae52dSmrg    XftDraw	*draw;
134c76ae52dSmrg
135c76ae52dSmrg    draw = (XftDraw *) malloc (sizeof (XftDraw));
136c76ae52dSmrg    if (!draw)
1370d590c07Smrg	return NULL;
1382836776bSmrg
139c76ae52dSmrg    draw->dpy = dpy;
140c76ae52dSmrg    draw->drawable = drawable;
141c76ae52dSmrg    draw->screen = _XftDrawScreen (dpy, drawable, visual);
142c76ae52dSmrg    draw->depth = 0;		/* don't find out unless we need to know */
143c76ae52dSmrg    draw->bits_per_pixel = 0;	/* don't find out unless we need to know */
144c76ae52dSmrg    draw->visual = visual;
145c76ae52dSmrg    draw->colormap = colormap;
146c76ae52dSmrg    draw->render.pict = 0;
1470d590c07Smrg    draw->core.gc = NULL;
148c76ae52dSmrg    draw->core.use_pixmap = 0;
149c76ae52dSmrg    draw->clip_type = XftClipTypeNone;
150c76ae52dSmrg    draw->subwindow_mode = ClipByChildren;
151c76ae52dSmrg    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
152c76ae52dSmrg    return draw;
153c76ae52dSmrg}
154c76ae52dSmrg
155c76ae52dSmrg_X_EXPORT XftDraw *
156c76ae52dSmrgXftDrawCreateBitmap (Display	*dpy,
157c76ae52dSmrg		     Pixmap	bitmap)
158c76ae52dSmrg{
159c76ae52dSmrg    XftDraw	*draw;
160c76ae52dSmrg
161c76ae52dSmrg    draw = (XftDraw *) malloc (sizeof (XftDraw));
162c76ae52dSmrg    if (!draw)
1630d590c07Smrg	return NULL;
164c76ae52dSmrg    draw->dpy = dpy;
165c76ae52dSmrg    draw->drawable = (Drawable) bitmap;
1660d590c07Smrg    draw->screen = _XftDrawScreen (dpy, bitmap, NULL);
167c76ae52dSmrg    draw->depth = 1;
168c76ae52dSmrg    draw->bits_per_pixel = 1;
1690d590c07Smrg    draw->visual = NULL;
170c76ae52dSmrg    draw->colormap = 0;
171c76ae52dSmrg    draw->render.pict = 0;
1720d590c07Smrg    draw->core.gc = NULL;
173c76ae52dSmrg    draw->core.use_pixmap = 0;
174c76ae52dSmrg    draw->clip_type = XftClipTypeNone;
175c76ae52dSmrg    draw->subwindow_mode = ClipByChildren;
176c76ae52dSmrg    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
177c76ae52dSmrg    return draw;
178c76ae52dSmrg}
179c76ae52dSmrg
180c76ae52dSmrg_X_EXPORT XftDraw *
181c76ae52dSmrgXftDrawCreateAlpha (Display *dpy,
182c76ae52dSmrg		    Pixmap  pixmap,
183c76ae52dSmrg		    int	    depth)
184c76ae52dSmrg{
185c76ae52dSmrg    XftDraw	*draw;
186c76ae52dSmrg
187c76ae52dSmrg    draw = (XftDraw *) malloc (sizeof (XftDraw));
188c76ae52dSmrg    if (!draw)
1890d590c07Smrg	return NULL;
190c76ae52dSmrg    draw->dpy = dpy;
191c76ae52dSmrg    draw->drawable = (Drawable) pixmap;
1920d590c07Smrg    draw->screen = _XftDrawScreen (dpy, pixmap, NULL);
193c76ae52dSmrg    draw->depth = depth;
194c76ae52dSmrg    draw->bits_per_pixel = 0;	/* don't find out until we need it */
1950d590c07Smrg    draw->visual = NULL;
196c76ae52dSmrg    draw->colormap = 0;
197c76ae52dSmrg    draw->render.pict = 0;
1980d590c07Smrg    draw->core.gc = NULL;
199c76ae52dSmrg    draw->core.use_pixmap = 0;
200c76ae52dSmrg    draw->clip_type = XftClipTypeNone;
201c76ae52dSmrg    draw->subwindow_mode = ClipByChildren;
202c76ae52dSmrg    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
203c76ae52dSmrg    return draw;
204c76ae52dSmrg}
205c76ae52dSmrg
206c76ae52dSmrgstatic XRenderPictFormat *
207c76ae52dSmrg_XftDrawFormat (XftDraw	*draw)
208c76ae52dSmrg{
209c76ae52dSmrg    XftDisplayInfo  *info = _XftDisplayInfoGet (draw->dpy, True);
210c76ae52dSmrg
211c76ae52dSmrg    if (!info || !info->hasRender)
2120d590c07Smrg	return NULL;
213c76ae52dSmrg
2140d590c07Smrg    if (draw->visual == NULL)
215c76ae52dSmrg    {
216c76ae52dSmrg	XRenderPictFormat   pf;
217c76ae52dSmrg
218c76ae52dSmrg	pf.type = PictTypeDirect;
219c76ae52dSmrg	pf.depth = XftDrawDepth (draw);
220c76ae52dSmrg	pf.direct.alpha = 0;
221c76ae52dSmrg	pf.direct.alphaMask = (1 << pf.depth) - 1;
222c76ae52dSmrg	return XRenderFindFormat (draw->dpy,
223c76ae52dSmrg				  (PictFormatType|
224c76ae52dSmrg				   PictFormatDepth|
225c76ae52dSmrg				   PictFormatAlpha|
226c76ae52dSmrg				   PictFormatAlphaMask),
227c76ae52dSmrg				  &pf,
228c76ae52dSmrg				  0);
229c76ae52dSmrg    }
230c76ae52dSmrg    else
231c76ae52dSmrg	return XRenderFindVisualFormat (draw->dpy, draw->visual);
232c76ae52dSmrg}
233c76ae52dSmrg
234c76ae52dSmrg_X_EXPORT void
235c76ae52dSmrgXftDrawChange (XftDraw	*draw,
236c76ae52dSmrg	       Drawable	drawable)
237c76ae52dSmrg{
238c76ae52dSmrg    draw->drawable = drawable;
239c76ae52dSmrg    if (draw->render.pict)
240c76ae52dSmrg    {
241c76ae52dSmrg	XRenderFreePicture (draw->dpy, draw->render.pict);
242c76ae52dSmrg	draw->render.pict = 0;
243c76ae52dSmrg    }
244c76ae52dSmrg    if (draw->core.gc)
245c76ae52dSmrg    {
246c76ae52dSmrg	XFreeGC (draw->dpy, draw->core.gc);
2470d590c07Smrg	draw->core.gc = NULL;
248c76ae52dSmrg    }
249c76ae52dSmrg}
250c76ae52dSmrg
251c76ae52dSmrg_X_EXPORT Display *
252c76ae52dSmrgXftDrawDisplay (XftDraw *draw)
253c76ae52dSmrg{
254c76ae52dSmrg    return draw->dpy;
255c76ae52dSmrg}
256c76ae52dSmrg
257c76ae52dSmrg_X_EXPORT Drawable
258c76ae52dSmrgXftDrawDrawable (XftDraw *draw)
259c76ae52dSmrg{
260c76ae52dSmrg    return draw->drawable;
261c76ae52dSmrg}
262c76ae52dSmrg
263c76ae52dSmrg_X_EXPORT Colormap
264c76ae52dSmrgXftDrawColormap (XftDraw *draw)
265c76ae52dSmrg{
266c76ae52dSmrg    return draw->colormap;
267c76ae52dSmrg}
268c76ae52dSmrg
269c76ae52dSmrg_X_EXPORT Visual *
270c76ae52dSmrgXftDrawVisual (XftDraw *draw)
271c76ae52dSmrg{
272c76ae52dSmrg    return draw->visual;
273c76ae52dSmrg}
274c76ae52dSmrg
275c76ae52dSmrg_X_EXPORT void
276c76ae52dSmrgXftDrawDestroy (XftDraw	*draw)
277c76ae52dSmrg{
278c76ae52dSmrg    if (draw->render.pict)
279c76ae52dSmrg	XRenderFreePicture (draw->dpy, draw->render.pict);
280c76ae52dSmrg    if (draw->core.gc)
281c76ae52dSmrg	XFreeGC (draw->dpy, draw->core.gc);
282c76ae52dSmrg    switch (draw->clip_type) {
283c76ae52dSmrg    case XftClipTypeRegion:
284c76ae52dSmrg	XDestroyRegion (draw->clip.region);
285c76ae52dSmrg	break;
286c76ae52dSmrg    case XftClipTypeRectangles:
287c76ae52dSmrg	free (draw->clip.rect);
288c76ae52dSmrg	break;
289c76ae52dSmrg    case XftClipTypeNone:
290c76ae52dSmrg	break;
291c76ae52dSmrg    }
292c76ae52dSmrg    XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw));
293c76ae52dSmrg    free (draw);
294c76ae52dSmrg}
295c76ae52dSmrg
296c76ae52dSmrg_X_EXPORT Picture
297c76ae52dSmrgXftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color)
298c76ae52dSmrg{
299c76ae52dSmrg    Display	    *dpy = draw->dpy;
300c76ae52dSmrg    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
301c76ae52dSmrg    int		    i;
302c76ae52dSmrg    XftColor	    bitmapColor;
303c76ae52dSmrg
3042836776bSmrg    if (!info || !info->solidFormat)
305c76ae52dSmrg	return 0;
3062836776bSmrg
307c76ae52dSmrg    /*
308c76ae52dSmrg     * Monochrome targets require special handling; the PictOp controls
309c76ae52dSmrg     * the color, and the color must be opaque
310c76ae52dSmrg     */
311c76ae52dSmrg    if (!draw->visual && draw->depth == 1)
312c76ae52dSmrg    {
313c76ae52dSmrg	bitmapColor.color.alpha = 0xffff;
314c76ae52dSmrg	bitmapColor.color.red   = 0xffff;
315c76ae52dSmrg	bitmapColor.color.green = 0xffff;
316c76ae52dSmrg	bitmapColor.color.blue  = 0xffff;
317c76ae52dSmrg	color = &bitmapColor;
318c76ae52dSmrg    }
319c76ae52dSmrg
320c76ae52dSmrg    /*
321c76ae52dSmrg     * See if there's one already available
322c76ae52dSmrg     */
323c76ae52dSmrg    for (i = 0; i < XFT_NUM_SOLID_COLOR; i++)
324c76ae52dSmrg    {
3252836776bSmrg	if (info->colors[i].pict &&
326c76ae52dSmrg	    info->colors[i].screen == draw->screen &&
3272836776bSmrg	    !memcmp ((void *) &color->color,
328c76ae52dSmrg		     (void *) &info->colors[i].color,
329c76ae52dSmrg		     sizeof (XRenderColor)))
330c76ae52dSmrg	    return info->colors[i].pict;
331c76ae52dSmrg    }
332c76ae52dSmrg    /*
333c76ae52dSmrg     * Pick one to replace at random
334c76ae52dSmrg     */
335c76ae52dSmrg    i = (unsigned int) rand () % XFT_NUM_SOLID_COLOR;
3368292847cSmrg
3378292847cSmrg    if (info->hasSolid) {
3388292847cSmrg	/*
3398292847cSmrg	 * Free any existing entry
3408292847cSmrg	 */
3418292847cSmrg	if (info->colors[i].pict)
3428292847cSmrg	    XRenderFreePicture (dpy, info->colors[i].pict);
3438292847cSmrg	/*
3448292847cSmrg	 * Create picture
3458292847cSmrg	 */
3468292847cSmrg	info->colors[i].pict = XRenderCreateSolidFill (draw->dpy, &color->color);
3478292847cSmrg    } else {
3488292847cSmrg	if (info->colors[i].screen != draw->screen && info->colors[i].pict)
3498292847cSmrg	{
3508292847cSmrg	    XRenderFreePicture (dpy, info->colors[i].pict);
3518292847cSmrg	    info->colors[i].pict = 0;
3528292847cSmrg	}
3538292847cSmrg	/*
3548292847cSmrg	 * Create picture if necessary
3558292847cSmrg	 */
3568292847cSmrg	if (!info->colors[i].pict)
3578292847cSmrg	{
3588292847cSmrg	    Pixmap			    pix;
3598292847cSmrg	    XRenderPictureAttributes    pa;
3608292847cSmrg
3618292847cSmrg	    pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1,
3628292847cSmrg				 info->solidFormat->depth);
3638292847cSmrg	    pa.repeat = True;
3648292847cSmrg	    info->colors[i].pict = XRenderCreatePicture (draw->dpy,
3658292847cSmrg							 pix,
3668292847cSmrg							 info->solidFormat,
3678292847cSmrg							 CPRepeat, &pa);
3688292847cSmrg	    XFreePixmap (dpy, pix);
3698292847cSmrg	}
3708292847cSmrg	/*
3718292847cSmrg	 * Set to the new color
3728292847cSmrg	 */
3738292847cSmrg	info->colors[i].color = color->color;
3748292847cSmrg	info->colors[i].screen = draw->screen;
3758292847cSmrg	XRenderFillRectangle (dpy, PictOpSrc,
3768292847cSmrg			      info->colors[i].pict,
3778292847cSmrg			      &color->color, 0, 0, 1, 1);
378c76ae52dSmrg    }
379c76ae52dSmrg    info->colors[i].color = color->color;
380c76ae52dSmrg    info->colors[i].screen = draw->screen;
3818292847cSmrg
382c76ae52dSmrg    return info->colors[i].pict;
383c76ae52dSmrg}
384c76ae52dSmrg
385c76ae52dSmrgstatic int
386c76ae52dSmrg_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color)
387c76ae52dSmrg{
388c76ae52dSmrg    if (draw->visual || draw->depth != 1)
389c76ae52dSmrg	return PictOpOver;
390c76ae52dSmrg    if (color->color.alpha >= 0x8000)
391c76ae52dSmrg	return PictOpOver;
392c76ae52dSmrg    return PictOpOutReverse;
393c76ae52dSmrg}
394c76ae52dSmrg
395c76ae52dSmrgstatic FcBool
396c76ae52dSmrg_XftDrawRenderPrepare (XftDraw	*draw)
397c76ae52dSmrg{
398c76ae52dSmrg    if (!draw->render.pict)
399c76ae52dSmrg    {
400c76ae52dSmrg	XRenderPictFormat	    *format;
401c76ae52dSmrg	XRenderPictureAttributes    pa;
402c76ae52dSmrg	unsigned long		    mask = 0;
403c76ae52dSmrg
404c76ae52dSmrg	format = _XftDrawFormat (draw);
405c76ae52dSmrg	if (!format)
406c76ae52dSmrg	    return FcFalse;
4072836776bSmrg
408c76ae52dSmrg	if (draw->subwindow_mode == IncludeInferiors)
409c76ae52dSmrg	{
410c76ae52dSmrg	    pa.subwindow_mode = IncludeInferiors;
411c76ae52dSmrg	    mask |= CPSubwindowMode;
412c76ae52dSmrg	}
413c76ae52dSmrg	draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable,
414c76ae52dSmrg						  format, mask, &pa);
415c76ae52dSmrg	if (!draw->render.pict)
416c76ae52dSmrg	    return FcFalse;
417c76ae52dSmrg	switch (draw->clip_type) {
418c76ae52dSmrg	case XftClipTypeRegion:
419c76ae52dSmrg	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
420c76ae52dSmrg					 draw->clip.region);
421c76ae52dSmrg	    break;
422c76ae52dSmrg	case XftClipTypeRectangles:
423c76ae52dSmrg	    XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
424c76ae52dSmrg					     draw->clip.rect->xOrigin,
425c76ae52dSmrg					     draw->clip.rect->yOrigin,
426c76ae52dSmrg					     XftClipRects(draw->clip.rect),
427c76ae52dSmrg					     draw->clip.rect->n);
428c76ae52dSmrg	    break;
429c76ae52dSmrg	case XftClipTypeNone:
430c76ae52dSmrg	    break;
431c76ae52dSmrg	}
432c76ae52dSmrg    }
433c76ae52dSmrg    return FcTrue;
434c76ae52dSmrg}
435c76ae52dSmrg
436c76ae52dSmrgstatic FcBool
437c76ae52dSmrg_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color)
438c76ae52dSmrg{
439c76ae52dSmrg    if (!draw->core.gc)
440c76ae52dSmrg    {
441c76ae52dSmrg	XGCValues	gcv;
442c76ae52dSmrg	unsigned long	mask = 0;
443c76ae52dSmrg	if (draw->subwindow_mode == IncludeInferiors)
444c76ae52dSmrg	{
445c76ae52dSmrg	    gcv.subwindow_mode = IncludeInferiors;
446c76ae52dSmrg	    mask |= GCSubwindowMode;
447c76ae52dSmrg	}
448c76ae52dSmrg	draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv);
449c76ae52dSmrg	if (!draw->core.gc)
450c76ae52dSmrg	    return FcFalse;
451c76ae52dSmrg	switch (draw->clip_type) {
452c76ae52dSmrg	case XftClipTypeRegion:
453c76ae52dSmrg	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
454c76ae52dSmrg	    break;
455c76ae52dSmrg	case XftClipTypeRectangles:
456c76ae52dSmrg	    XSetClipRectangles (draw->dpy, draw->core.gc,
457c76ae52dSmrg				draw->clip.rect->xOrigin,
458c76ae52dSmrg				draw->clip.rect->yOrigin,
459c76ae52dSmrg				XftClipRects (draw->clip.rect),
460c76ae52dSmrg				draw->clip.rect->n,
461c76ae52dSmrg				Unsorted);
462c76ae52dSmrg	    break;
463c76ae52dSmrg	case XftClipTypeNone:
464c76ae52dSmrg	    break;
465c76ae52dSmrg	}
466c76ae52dSmrg    }
467c76ae52dSmrg    XSetForeground (draw->dpy, draw->core.gc, color->pixel);
468c76ae52dSmrg    return FcTrue;
469c76ae52dSmrg}
4702836776bSmrg
471c76ae52dSmrg_X_EXPORT Picture
472c76ae52dSmrgXftDrawPicture (XftDraw *draw)
473c76ae52dSmrg{
474c76ae52dSmrg    if (!_XftDrawRenderPrepare (draw))
475c76ae52dSmrg	return 0;
476c76ae52dSmrg    return draw->render.pict;
477c76ae52dSmrg}
478c76ae52dSmrg
479c76ae52dSmrg#define NUM_LOCAL   1024
480c76ae52dSmrg
481c76ae52dSmrg_X_EXPORT void
482c76ae52dSmrgXftDrawGlyphs (XftDraw		*draw,
483c76ae52dSmrg	       _Xconst XftColor	*color,
484c76ae52dSmrg	       XftFont		*pub,
485c76ae52dSmrg	       int		x,
486c76ae52dSmrg	       int		y,
487c76ae52dSmrg	       _Xconst FT_UInt	*glyphs,
488c76ae52dSmrg	       int		nglyphs)
489c76ae52dSmrg{
490c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
491c76ae52dSmrg
492c76ae52dSmrg    if (font->format)
493c76ae52dSmrg    {
494c76ae52dSmrg	Picture	    src;
4952836776bSmrg
496c76ae52dSmrg	if (_XftDrawRenderPrepare (draw) &&
497c76ae52dSmrg	    (src = XftDrawSrcPicture (draw, color)))
498c76ae52dSmrg	    XftGlyphRender (draw->dpy, _XftDrawOp (draw, color),
499c76ae52dSmrg			     src, pub, draw->render.pict,
500c76ae52dSmrg			     0, 0, x, y, glyphs, nglyphs);
501c76ae52dSmrg    }
502c76ae52dSmrg    else
503c76ae52dSmrg    {
504c76ae52dSmrg	if (_XftDrawCorePrepare (draw, color))
505c76ae52dSmrg	    XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs);
506c76ae52dSmrg    }
507c76ae52dSmrg}
508c76ae52dSmrg
509c76ae52dSmrg_X_EXPORT void
510c76ae52dSmrgXftDrawString8 (XftDraw		    *draw,
511c76ae52dSmrg		_Xconst XftColor    *color,
512c76ae52dSmrg		XftFont		    *pub,
5132836776bSmrg		int		    x,
514c76ae52dSmrg		int		    y,
515c76ae52dSmrg		_Xconst FcChar8	    *string,
516c76ae52dSmrg		int		    len)
517c76ae52dSmrg{
518c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
519c76ae52dSmrg    int		    i;
520c76ae52dSmrg
521c76ae52dSmrg    if (XftDebug () & XFT_DBG_DRAW)
522c76ae52dSmrg	printf ("DrawString \"%*.*s\"\n", len, len, string);
5232836776bSmrg
524c76ae52dSmrg    if (len <= NUM_LOCAL)
525c76ae52dSmrg	glyphs = glyphs_local;
526c76ae52dSmrg    else
527c76ae52dSmrg    {
528c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
529c76ae52dSmrg	if (!glyphs)
530c76ae52dSmrg	    return;
531c76ae52dSmrg    }
532c76ae52dSmrg    for (i = 0; i < len; i++)
533c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
534c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
535c76ae52dSmrg    if (glyphs != glyphs_local)
536c76ae52dSmrg	free (glyphs);
537c76ae52dSmrg}
538c76ae52dSmrg
539c76ae52dSmrg_X_EXPORT void
540c76ae52dSmrgXftDrawString16 (XftDraw	    *draw,
541c76ae52dSmrg		 _Xconst XftColor   *color,
542c76ae52dSmrg		 XftFont	    *pub,
543c76ae52dSmrg		 int		    x,
544c76ae52dSmrg		 int		    y,
545c76ae52dSmrg		 _Xconst FcChar16   *string,
546c76ae52dSmrg		 int		    len)
547c76ae52dSmrg{
548c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
549c76ae52dSmrg    int		    i;
550c76ae52dSmrg
551c76ae52dSmrg    if (len <= NUM_LOCAL)
552c76ae52dSmrg	glyphs = glyphs_local;
553c76ae52dSmrg    else
554c76ae52dSmrg    {
555c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
556c76ae52dSmrg	if (!glyphs)
557c76ae52dSmrg	    return;
558c76ae52dSmrg    }
559c76ae52dSmrg    for (i = 0; i < len; i++)
560c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
5612836776bSmrg
562c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
563c76ae52dSmrg    if (glyphs != glyphs_local)
564c76ae52dSmrg	free (glyphs);
565c76ae52dSmrg}
566c76ae52dSmrg
567c76ae52dSmrg_X_EXPORT void
568c76ae52dSmrgXftDrawString32 (XftDraw	    *draw,
569c76ae52dSmrg		 _Xconst XftColor   *color,
570c76ae52dSmrg		 XftFont	    *pub,
571c76ae52dSmrg		 int		    x,
572c76ae52dSmrg		 int		    y,
573c76ae52dSmrg		 _Xconst FcChar32   *string,
574c76ae52dSmrg		 int		    len)
575c76ae52dSmrg{
576c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
577c76ae52dSmrg    int		    i;
578c76ae52dSmrg
579c76ae52dSmrg    if (len <= NUM_LOCAL)
580c76ae52dSmrg	glyphs = glyphs_local;
581c76ae52dSmrg    else
582c76ae52dSmrg    {
583c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
584c76ae52dSmrg	if (!glyphs)
585c76ae52dSmrg	    return;
586c76ae52dSmrg    }
587c76ae52dSmrg    for (i = 0; i < len; i++)
588c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
5892836776bSmrg
590c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
591c76ae52dSmrg    if (glyphs != glyphs_local)
592c76ae52dSmrg	free (glyphs);
593c76ae52dSmrg}
594c76ae52dSmrg
595c76ae52dSmrg_X_EXPORT void
596c76ae52dSmrgXftDrawStringUtf8 (XftDraw	    *draw,
597c76ae52dSmrg		   _Xconst XftColor *color,
598c76ae52dSmrg		   XftFont	    *pub,
5992836776bSmrg		   int		    x,
600c76ae52dSmrg		   int		    y,
601c76ae52dSmrg		   _Xconst FcChar8  *string,
602c76ae52dSmrg		   int		    len)
603c76ae52dSmrg{
604c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
605c76ae52dSmrg    FcChar32	    ucs4;
606c76ae52dSmrg    int		    i;
607c76ae52dSmrg    int		    l;
608c76ae52dSmrg    int		    size;
609c76ae52dSmrg
610c76ae52dSmrg    i = 0;
611c76ae52dSmrg    glyphs = glyphs_local;
612c76ae52dSmrg    size = NUM_LOCAL;
613c76ae52dSmrg    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
614c76ae52dSmrg    {
615c76ae52dSmrg	if (i == size)
616c76ae52dSmrg	{
617c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
618c76ae52dSmrg	    if (!glyphs_new)
619c76ae52dSmrg	    {
620c76ae52dSmrg		if (glyphs != glyphs_local)
621c76ae52dSmrg		    free (glyphs);
622c76ae52dSmrg		return;
623c76ae52dSmrg	    }
624c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
625c76ae52dSmrg	    size *= 2;
626c76ae52dSmrg	    if (glyphs != glyphs_local)
627c76ae52dSmrg		free (glyphs);
628c76ae52dSmrg	    glyphs = glyphs_new;
629c76ae52dSmrg	}
630c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
631c76ae52dSmrg	string += l;
632c76ae52dSmrg	len -= l;
633c76ae52dSmrg    }
634c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
635c76ae52dSmrg    if (glyphs != glyphs_local)
636c76ae52dSmrg	free (glyphs);
637c76ae52dSmrg}
638c76ae52dSmrg
639c76ae52dSmrg_X_EXPORT void
640c76ae52dSmrgXftDrawStringUtf16 (XftDraw		*draw,
641c76ae52dSmrg		    _Xconst XftColor	*color,
642c76ae52dSmrg		    XftFont		*pub,
643c76ae52dSmrg		    int			x,
644c76ae52dSmrg		    int			y,
645c76ae52dSmrg		    _Xconst FcChar8	*string,
646c76ae52dSmrg		    FcEndian		endian,
647c76ae52dSmrg		    int			len)
648c76ae52dSmrg{
649c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
650c76ae52dSmrg    FcChar32	    ucs4;
651c76ae52dSmrg    int		    i;
652c76ae52dSmrg    int		    l;
653c76ae52dSmrg    int		    size;
654c76ae52dSmrg
655c76ae52dSmrg    i = 0;
656c76ae52dSmrg    glyphs = glyphs_local;
657c76ae52dSmrg    size = NUM_LOCAL;
658c76ae52dSmrg    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
659c76ae52dSmrg    {
660c76ae52dSmrg	if (i == size)
661c76ae52dSmrg	{
662c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
663c76ae52dSmrg	    if (!glyphs_new)
664c76ae52dSmrg	    {
665c76ae52dSmrg		if (glyphs != glyphs_local)
666c76ae52dSmrg		    free (glyphs);
667c76ae52dSmrg		return;
668c76ae52dSmrg	    }
669c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
670c76ae52dSmrg	    size *= 2;
671c76ae52dSmrg	    if (glyphs != glyphs_local)
672c76ae52dSmrg		free (glyphs);
673c76ae52dSmrg	    glyphs = glyphs_new;
674c76ae52dSmrg	}
675c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
676c76ae52dSmrg	string += l;
677c76ae52dSmrg	len -= l;
678c76ae52dSmrg    }
679c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
680c76ae52dSmrg    if (glyphs != glyphs_local)
681c76ae52dSmrg	free (glyphs);
682c76ae52dSmrg}
683c76ae52dSmrg
684c76ae52dSmrg_X_EXPORT void
685c76ae52dSmrgXftDrawGlyphSpec (XftDraw		*draw,
686c76ae52dSmrg		  _Xconst XftColor	*color,
687c76ae52dSmrg		  XftFont		*pub,
688c76ae52dSmrg		  _Xconst XftGlyphSpec	*glyphs,
689c76ae52dSmrg		  int			len)
690c76ae52dSmrg{
691c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
692c76ae52dSmrg
693c76ae52dSmrg    if (font->format)
694c76ae52dSmrg    {
695c76ae52dSmrg	Picture	src;
696c76ae52dSmrg
697c76ae52dSmrg	if (_XftDrawRenderPrepare (draw) &&
698c76ae52dSmrg	    (src = XftDrawSrcPicture (draw, color)))
699c76ae52dSmrg	{
700c76ae52dSmrg	    XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color),
701c76ae52dSmrg				src, pub, draw->render.pict,
702c76ae52dSmrg				0, 0, glyphs, len);
703c76ae52dSmrg	}
704c76ae52dSmrg    }
705c76ae52dSmrg    else
706c76ae52dSmrg    {
707c76ae52dSmrg	if (_XftDrawCorePrepare (draw, color))
708c76ae52dSmrg	    XftGlyphSpecCore (draw, color, pub, glyphs, len);
709c76ae52dSmrg    }
710c76ae52dSmrg}
711c76ae52dSmrg
712c76ae52dSmrg_X_EXPORT void
713c76ae52dSmrgXftDrawGlyphFontSpec (XftDraw			*draw,
714c76ae52dSmrg		      _Xconst XftColor		*color,
715c76ae52dSmrg		      _Xconst XftGlyphFontSpec	*glyphs,
716c76ae52dSmrg		      int			len)
717c76ae52dSmrg{
718c76ae52dSmrg    int		i;
719c76ae52dSmrg    int		start;
720c76ae52dSmrg
721c76ae52dSmrg    i = 0;
722c76ae52dSmrg    while (i < len)
723c76ae52dSmrg    {
724c76ae52dSmrg	start = i;
725c76ae52dSmrg	if (((XftFontInt *) glyphs[i].font)->format)
726c76ae52dSmrg	{
727c76ae52dSmrg	    Picture	src;
728c76ae52dSmrg	    while (i < len && ((XftFontInt *) glyphs[i].font)->format)
729c76ae52dSmrg		i++;
730c76ae52dSmrg	    if (_XftDrawRenderPrepare (draw) &&
731c76ae52dSmrg		(src = XftDrawSrcPicture (draw, color)))
732c76ae52dSmrg	    {
733c76ae52dSmrg		XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color),
734c76ae52dSmrg					src, draw->render.pict,
735c76ae52dSmrg					0, 0, glyphs + start , i - start);
736c76ae52dSmrg	    }
737c76ae52dSmrg	}
738c76ae52dSmrg	else
739c76ae52dSmrg	{
740c76ae52dSmrg	    while (i < len && !((XftFontInt *) glyphs[i].font)->format)
741c76ae52dSmrg		i++;
742c76ae52dSmrg	    if (_XftDrawCorePrepare (draw, color))
743c76ae52dSmrg		XftGlyphFontSpecCore (draw, color, glyphs + start, i - start);
744c76ae52dSmrg	}
745c76ae52dSmrg    }
746c76ae52dSmrg}
747c76ae52dSmrg
748c76ae52dSmrg_X_EXPORT void
749c76ae52dSmrgXftDrawCharSpec (XftDraw		*draw,
750c76ae52dSmrg		 _Xconst XftColor	*color,
751c76ae52dSmrg		 XftFont		*pub,
752c76ae52dSmrg		 _Xconst XftCharSpec	*chars,
753c76ae52dSmrg		 int			len)
754c76ae52dSmrg{
755c76ae52dSmrg    XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
756c76ae52dSmrg    int		    i;
757c76ae52dSmrg
758c76ae52dSmrg    if (len <= NUM_LOCAL)
759c76ae52dSmrg	glyphs = glyphs_local;
760c76ae52dSmrg    else
761c76ae52dSmrg    {
762c76ae52dSmrg	glyphs = malloc (len * sizeof (XftGlyphSpec));
763c76ae52dSmrg	if (!glyphs)
764c76ae52dSmrg	    return;
765c76ae52dSmrg    }
766c76ae52dSmrg    for (i = 0; i < len; i++)
767c76ae52dSmrg    {
768c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4);
769c76ae52dSmrg	glyphs[i].x = chars[i].x;
770c76ae52dSmrg	glyphs[i].y = chars[i].y;
771c76ae52dSmrg    }
772c76ae52dSmrg
773c76ae52dSmrg    XftDrawGlyphSpec (draw, color, pub, glyphs, len);
774c76ae52dSmrg    if (glyphs != glyphs_local)
775c76ae52dSmrg	free (glyphs);
776c76ae52dSmrg}
777c76ae52dSmrg
778c76ae52dSmrg_X_EXPORT void
779c76ae52dSmrgXftDrawCharFontSpec (XftDraw			*draw,
780c76ae52dSmrg		     _Xconst XftColor		*color,
781c76ae52dSmrg		     _Xconst XftCharFontSpec	*chars,
782c76ae52dSmrg		     int			len)
783c76ae52dSmrg{
784c76ae52dSmrg    XftGlyphFontSpec	*glyphs, glyphs_local[NUM_LOCAL];
785c76ae52dSmrg    int			i;
786c76ae52dSmrg
787c76ae52dSmrg    if (len <= NUM_LOCAL)
788c76ae52dSmrg	glyphs = glyphs_local;
789c76ae52dSmrg    else
790c76ae52dSmrg    {
791c76ae52dSmrg	glyphs = malloc (len * sizeof (XftGlyphFontSpec));
792c76ae52dSmrg	if (!glyphs)
793c76ae52dSmrg	    return;
794c76ae52dSmrg    }
795c76ae52dSmrg    for (i = 0; i < len; i++)
796c76ae52dSmrg    {
797c76ae52dSmrg	glyphs[i].font = chars[i].font;
798c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4);
799c76ae52dSmrg	glyphs[i].x = chars[i].x;
800c76ae52dSmrg	glyphs[i].y = chars[i].y;
801c76ae52dSmrg    }
802c76ae52dSmrg
803c76ae52dSmrg    XftDrawGlyphFontSpec (draw, color, glyphs, len);
804c76ae52dSmrg    if (glyphs != glyphs_local)
805c76ae52dSmrg	free (glyphs);
806c76ae52dSmrg}
807c76ae52dSmrg
808c76ae52dSmrg_X_EXPORT void
809c76ae52dSmrgXftDrawRect (XftDraw		*draw,
810c76ae52dSmrg	     _Xconst XftColor	*color,
8112836776bSmrg	     int		x,
812c76ae52dSmrg	     int		y,
813c76ae52dSmrg	     unsigned int	width,
814c76ae52dSmrg	     unsigned int	height)
815c76ae52dSmrg{
816c76ae52dSmrg    if (_XftDrawRenderPrepare (draw))
817c76ae52dSmrg    {
818c76ae52dSmrg	XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict,
819c76ae52dSmrg			      &color->color, x, y, width, height);
820c76ae52dSmrg    }
821c76ae52dSmrg    else if (_XftDrawCorePrepare (draw, color))
822c76ae52dSmrg    {
8230d590c07Smrg	/* note: not XftRectCore() */
8240d590c07Smrg	XSetForeground (draw->dpy, draw->core.gc, color->pixel);
8250d590c07Smrg	XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
8260d590c07Smrg			x, y, width, height);
827c76ae52dSmrg    }
828c76ae52dSmrg}
829c76ae52dSmrg
830c76ae52dSmrg_X_EXPORT Bool
831c76ae52dSmrgXftDrawSetClip (XftDraw	*draw,
832c76ae52dSmrg		Region	r)
833c76ae52dSmrg{
8340d590c07Smrg    Region			n = NULL;
835c76ae52dSmrg
836c76ae52dSmrg    /*
837c76ae52dSmrg     * Check for quick exits
838c76ae52dSmrg     */
839c76ae52dSmrg    if (!r && draw->clip_type == XftClipTypeNone)
840c76ae52dSmrg	return True;
8412836776bSmrg
8422836776bSmrg    if (r &&
8432836776bSmrg	draw->clip_type == XftClipTypeRegion &&
844c76ae52dSmrg	XEqualRegion (r, draw->clip.region))
845c76ae52dSmrg    {
846c76ae52dSmrg	return True;
847c76ae52dSmrg    }
848c76ae52dSmrg
849c76ae52dSmrg    /*
850c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
851c76ae52dSmrg     */
852c76ae52dSmrg    if (r)
853c76ae52dSmrg    {
854c76ae52dSmrg	n = XCreateRegion ();
855c76ae52dSmrg	if (n)
856c76ae52dSmrg	{
857c76ae52dSmrg	    if (!XUnionRegion (n, r, n))
858c76ae52dSmrg	    {
859c76ae52dSmrg		XDestroyRegion (n);
860c76ae52dSmrg		return False;
861c76ae52dSmrg	    }
862c76ae52dSmrg	}
863c76ae52dSmrg    }
864c76ae52dSmrg
865c76ae52dSmrg    /*
866c76ae52dSmrg     * Destroy existing clip
867c76ae52dSmrg     */
868c76ae52dSmrg    switch (draw->clip_type) {
869c76ae52dSmrg    case XftClipTypeRegion:
870c76ae52dSmrg	XDestroyRegion (draw->clip.region);
871c76ae52dSmrg	break;
872c76ae52dSmrg    case XftClipTypeRectangles:
873c76ae52dSmrg	free (draw->clip.rect);
874c76ae52dSmrg	break;
875c76ae52dSmrg    case XftClipTypeNone:
876c76ae52dSmrg	break;
877c76ae52dSmrg    }
8782836776bSmrg
879c76ae52dSmrg    /*
880c76ae52dSmrg     * Set the clip
881c76ae52dSmrg     */
882c76ae52dSmrg    if (n)
883c76ae52dSmrg    {
884c76ae52dSmrg	draw->clip_type = XftClipTypeRegion;
885c76ae52dSmrg	draw->clip.region = n;
886c76ae52dSmrg    }
887c76ae52dSmrg    else
888c76ae52dSmrg    {
889c76ae52dSmrg	draw->clip_type = XftClipTypeNone;
890c76ae52dSmrg    }
891c76ae52dSmrg    /*
892c76ae52dSmrg     * Apply new clip to existing objects
893c76ae52dSmrg     */
894c76ae52dSmrg    if (draw->render.pict)
895c76ae52dSmrg    {
896c76ae52dSmrg	if (n)
897c76ae52dSmrg	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n);
898c76ae52dSmrg	else
899c76ae52dSmrg	{
900c76ae52dSmrg	    XRenderPictureAttributes	pa;
901c76ae52dSmrg	    pa.clip_mask = None;
902c76ae52dSmrg	    XRenderChangePicture (draw->dpy, draw->render.pict,
903c76ae52dSmrg				  CPClipMask, &pa);
904c76ae52dSmrg	}
905c76ae52dSmrg    }
906c76ae52dSmrg    if (draw->core.gc)
907c76ae52dSmrg    {
908c76ae52dSmrg	if (n)
909c76ae52dSmrg	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
910c76ae52dSmrg	else
911c76ae52dSmrg	    XSetClipMask (draw->dpy, draw->core.gc, None);
912c76ae52dSmrg    }
913c76ae52dSmrg    return True;
914c76ae52dSmrg}
915c76ae52dSmrg
916c76ae52dSmrg_X_EXPORT Bool
917c76ae52dSmrgXftDrawSetClipRectangles (XftDraw		*draw,
918c76ae52dSmrg			  int			xOrigin,
919c76ae52dSmrg			  int			yOrigin,
920c76ae52dSmrg			  _Xconst XRectangle	*rects,
921c76ae52dSmrg			  int			n)
922c76ae52dSmrg{
9230d590c07Smrg    XftClipRect	*new = NULL;
924c76ae52dSmrg
925c76ae52dSmrg    /*
926c76ae52dSmrg     * Check for quick exit
927c76ae52dSmrg     */
928c76ae52dSmrg    if (draw->clip_type == XftClipTypeRectangles &&
929c76ae52dSmrg	draw->clip.rect->n == n &&
930c76ae52dSmrg	(n == 0 || (draw->clip.rect->xOrigin == xOrigin &&
931c76ae52dSmrg		    draw->clip.rect->yOrigin == yOrigin)) &&
932c76ae52dSmrg	!memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle)))
933c76ae52dSmrg    {
934c76ae52dSmrg	return True;
935c76ae52dSmrg    }
936c76ae52dSmrg
937c76ae52dSmrg    /*
938c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
939c76ae52dSmrg     */
940c76ae52dSmrg    new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle));
941c76ae52dSmrg    if (!new)
942c76ae52dSmrg	return False;
943c76ae52dSmrg
944c76ae52dSmrg    new->n = n;
945c76ae52dSmrg    new->xOrigin = xOrigin;
946c76ae52dSmrg    new->yOrigin = yOrigin;
947c76ae52dSmrg    memcpy (XftClipRects (new), rects, n * sizeof (XRectangle));
948c76ae52dSmrg
949c76ae52dSmrg    /*
950c76ae52dSmrg     * Destroy existing clip
951c76ae52dSmrg     */
952c76ae52dSmrg    switch (draw->clip_type) {
953c76ae52dSmrg    case XftClipTypeRegion:
954c76ae52dSmrg	XDestroyRegion (draw->clip.region);
955c76ae52dSmrg	break;
956c76ae52dSmrg    case XftClipTypeRectangles:
957c76ae52dSmrg	free (draw->clip.rect);
958c76ae52dSmrg	break;
959c76ae52dSmrg    case XftClipTypeNone:
960c76ae52dSmrg	break;
961c76ae52dSmrg    }
9622836776bSmrg
963c76ae52dSmrg    /*
964c76ae52dSmrg     * Set the clip
965c76ae52dSmrg     */
966c76ae52dSmrg    draw->clip_type = XftClipTypeRectangles;
967c76ae52dSmrg    draw->clip.rect = new;
968c76ae52dSmrg    /*
969c76ae52dSmrg     * Apply new clip to existing objects
970c76ae52dSmrg     */
971c76ae52dSmrg    if (draw->render.pict)
972c76ae52dSmrg    {
973c76ae52dSmrg	XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
974c76ae52dSmrg					 new->xOrigin,
975c76ae52dSmrg					 new->yOrigin,
976c76ae52dSmrg					 XftClipRects(new),
977c76ae52dSmrg					 new->n);
978c76ae52dSmrg    }
979c76ae52dSmrg    if (draw->core.gc)
980c76ae52dSmrg    {
981c76ae52dSmrg	XSetClipRectangles (draw->dpy, draw->core.gc,
982c76ae52dSmrg			    new->xOrigin,
983c76ae52dSmrg			    new->yOrigin,
984c76ae52dSmrg			    XftClipRects (new),
985c76ae52dSmrg			    new->n,
986c76ae52dSmrg			    Unsorted);
987c76ae52dSmrg    }
988c76ae52dSmrg    return True;
989c76ae52dSmrg}
990c76ae52dSmrg
991c76ae52dSmrg_X_EXPORT void
992c76ae52dSmrgXftDrawSetSubwindowMode (XftDraw *draw, int mode)
993c76ae52dSmrg{
994c76ae52dSmrg    if (mode == draw->subwindow_mode)
995c76ae52dSmrg	return;
996c76ae52dSmrg    draw->subwindow_mode = mode;
997c76ae52dSmrg    if (draw->render.pict)
998c76ae52dSmrg    {
999c76ae52dSmrg	XRenderPictureAttributes    pa;
1000c76ae52dSmrg
1001c76ae52dSmrg	pa.subwindow_mode = mode;
10022836776bSmrg	XRenderChangePicture (draw->dpy, draw->render.pict,
1003c76ae52dSmrg			      CPSubwindowMode, &pa);
1004c76ae52dSmrg    }
1005c76ae52dSmrg    if (draw->core.gc)
1006c76ae52dSmrg	XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
1007c76ae52dSmrg}
1008