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	    {
115de3c0529Smrg		if ((unsigned) formats[i].depth == depth)
116c76ae52dSmrg		{
11784febdacSmrg		    draw->bits_per_pixel = (unsigned)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
135de3c0529Smrg    draw = 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
161de3c0529Smrg    draw = 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
187de3c0529Smrg    draw = 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);
19384febdacSmrg    draw->depth = (unsigned)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;
21984febdacSmrg	pf.depth = (int)XftDrawDepth (draw);
220c76ae52dSmrg	pf.direct.alpha = 0;
22184febdacSmrg	pf.direct.alphaMask = (short)((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 &&
327de3c0529Smrg	    !memcmp ((const void *) &color->color,
328de3c0529Smrg		     (const 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,
36284febdacSmrg				 (unsigned)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    {
528de3c0529Smrg	glyphs = AllocUIntArray (len);
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
551de3c0529Smrg    if (len <= 0)
552de3c0529Smrg	return;
553de3c0529Smrg
554c76ae52dSmrg    if (len <= NUM_LOCAL)
555c76ae52dSmrg	glyphs = glyphs_local;
556c76ae52dSmrg    else
557c76ae52dSmrg    {
558de3c0529Smrg	glyphs = AllocUIntArray (len);
559c76ae52dSmrg	if (!glyphs)
560c76ae52dSmrg	    return;
561c76ae52dSmrg    }
562c76ae52dSmrg    for (i = 0; i < len; i++)
563c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
5642836776bSmrg
565c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
566c76ae52dSmrg    if (glyphs != glyphs_local)
567c76ae52dSmrg	free (glyphs);
568c76ae52dSmrg}
569c76ae52dSmrg
570c76ae52dSmrg_X_EXPORT void
571c76ae52dSmrgXftDrawString32 (XftDraw	    *draw,
572c76ae52dSmrg		 _Xconst XftColor   *color,
573c76ae52dSmrg		 XftFont	    *pub,
574c76ae52dSmrg		 int		    x,
575c76ae52dSmrg		 int		    y,
576c76ae52dSmrg		 _Xconst FcChar32   *string,
577c76ae52dSmrg		 int		    len)
578c76ae52dSmrg{
579c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
580c76ae52dSmrg    int		    i;
581c76ae52dSmrg
582de3c0529Smrg    if (len <= 0)
583de3c0529Smrg	return;
584de3c0529Smrg
585c76ae52dSmrg    if (len <= NUM_LOCAL)
586c76ae52dSmrg	glyphs = glyphs_local;
587c76ae52dSmrg    else
588c76ae52dSmrg    {
589de3c0529Smrg	glyphs = AllocUIntArray (len);
590c76ae52dSmrg	if (!glyphs)
591c76ae52dSmrg	    return;
592c76ae52dSmrg    }
593c76ae52dSmrg    for (i = 0; i < len; i++)
594c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
5952836776bSmrg
596c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
597c76ae52dSmrg    if (glyphs != glyphs_local)
598c76ae52dSmrg	free (glyphs);
599c76ae52dSmrg}
600c76ae52dSmrg
601c76ae52dSmrg_X_EXPORT void
602c76ae52dSmrgXftDrawStringUtf8 (XftDraw	    *draw,
603c76ae52dSmrg		   _Xconst XftColor *color,
604c76ae52dSmrg		   XftFont	    *pub,
6052836776bSmrg		   int		    x,
606c76ae52dSmrg		   int		    y,
607c76ae52dSmrg		   _Xconst FcChar8  *string,
608c76ae52dSmrg		   int		    len)
609c76ae52dSmrg{
610c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
611c76ae52dSmrg    FcChar32	    ucs4;
612c76ae52dSmrg    int		    i;
613c76ae52dSmrg    int		    l;
614c76ae52dSmrg    int		    size;
615c76ae52dSmrg
616de3c0529Smrg    if (len <= 0)
617de3c0529Smrg	return;
618de3c0529Smrg
619c76ae52dSmrg    i = 0;
620c76ae52dSmrg    glyphs = glyphs_local;
621c76ae52dSmrg    size = NUM_LOCAL;
622c76ae52dSmrg    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
623c76ae52dSmrg    {
624c76ae52dSmrg	if (i == size)
625c76ae52dSmrg	{
626de3c0529Smrg	    glyphs_new = AllocUIntArray (size * 2);
627c76ae52dSmrg	    if (!glyphs_new)
628c76ae52dSmrg	    {
629c76ae52dSmrg		if (glyphs != glyphs_local)
630c76ae52dSmrg		    free (glyphs);
631c76ae52dSmrg		return;
632c76ae52dSmrg	    }
63384febdacSmrg	    memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt));
634c76ae52dSmrg	    size *= 2;
635c76ae52dSmrg	    if (glyphs != glyphs_local)
636c76ae52dSmrg		free (glyphs);
637c76ae52dSmrg	    glyphs = glyphs_new;
638c76ae52dSmrg	}
639c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
640c76ae52dSmrg	string += l;
641c76ae52dSmrg	len -= l;
642c76ae52dSmrg    }
643c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
644c76ae52dSmrg    if (glyphs != glyphs_local)
645c76ae52dSmrg	free (glyphs);
646c76ae52dSmrg}
647c76ae52dSmrg
648c76ae52dSmrg_X_EXPORT void
649c76ae52dSmrgXftDrawStringUtf16 (XftDraw		*draw,
650c76ae52dSmrg		    _Xconst XftColor	*color,
651c76ae52dSmrg		    XftFont		*pub,
652c76ae52dSmrg		    int			x,
653c76ae52dSmrg		    int			y,
654c76ae52dSmrg		    _Xconst FcChar8	*string,
655c76ae52dSmrg		    FcEndian		endian,
656c76ae52dSmrg		    int			len)
657c76ae52dSmrg{
658c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
659c76ae52dSmrg    FcChar32	    ucs4;
660c76ae52dSmrg    int		    i;
661c76ae52dSmrg    int		    l;
662c76ae52dSmrg    int		    size;
663c76ae52dSmrg
664de3c0529Smrg    if (len <= 0)
665de3c0529Smrg	return;
666de3c0529Smrg
667c76ae52dSmrg    i = 0;
668c76ae52dSmrg    glyphs = glyphs_local;
669c76ae52dSmrg    size = NUM_LOCAL;
670c76ae52dSmrg    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
671c76ae52dSmrg    {
672c76ae52dSmrg	if (i == size)
673c76ae52dSmrg	{
674de3c0529Smrg	    glyphs_new = AllocUIntArray (size * 2);
675c76ae52dSmrg	    if (!glyphs_new)
676c76ae52dSmrg	    {
677c76ae52dSmrg		if (glyphs != glyphs_local)
678c76ae52dSmrg		    free (glyphs);
679c76ae52dSmrg		return;
680c76ae52dSmrg	    }
68184febdacSmrg	    memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt));
682c76ae52dSmrg	    size *= 2;
683c76ae52dSmrg	    if (glyphs != glyphs_local)
684c76ae52dSmrg		free (glyphs);
685c76ae52dSmrg	    glyphs = glyphs_new;
686c76ae52dSmrg	}
687c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
688c76ae52dSmrg	string += l;
689c76ae52dSmrg	len -= l;
690c76ae52dSmrg    }
691c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
692c76ae52dSmrg    if (glyphs != glyphs_local)
693c76ae52dSmrg	free (glyphs);
694c76ae52dSmrg}
695c76ae52dSmrg
696c76ae52dSmrg_X_EXPORT void
697c76ae52dSmrgXftDrawGlyphSpec (XftDraw		*draw,
698c76ae52dSmrg		  _Xconst XftColor	*color,
699c76ae52dSmrg		  XftFont		*pub,
700c76ae52dSmrg		  _Xconst XftGlyphSpec	*glyphs,
701c76ae52dSmrg		  int			len)
702c76ae52dSmrg{
703c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
704c76ae52dSmrg
705c76ae52dSmrg    if (font->format)
706c76ae52dSmrg    {
707c76ae52dSmrg	Picture	src;
708c76ae52dSmrg
709c76ae52dSmrg	if (_XftDrawRenderPrepare (draw) &&
710c76ae52dSmrg	    (src = XftDrawSrcPicture (draw, color)))
711c76ae52dSmrg	{
712c76ae52dSmrg	    XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color),
713c76ae52dSmrg				src, pub, draw->render.pict,
714c76ae52dSmrg				0, 0, glyphs, len);
715c76ae52dSmrg	}
716c76ae52dSmrg    }
717c76ae52dSmrg    else
718c76ae52dSmrg    {
719c76ae52dSmrg	if (_XftDrawCorePrepare (draw, color))
720c76ae52dSmrg	    XftGlyphSpecCore (draw, color, pub, glyphs, len);
721c76ae52dSmrg    }
722c76ae52dSmrg}
723c76ae52dSmrg
724c76ae52dSmrg_X_EXPORT void
725c76ae52dSmrgXftDrawGlyphFontSpec (XftDraw			*draw,
726c76ae52dSmrg		      _Xconst XftColor		*color,
727c76ae52dSmrg		      _Xconst XftGlyphFontSpec	*glyphs,
728c76ae52dSmrg		      int			len)
729c76ae52dSmrg{
730c76ae52dSmrg    int		i;
731c76ae52dSmrg    int		start;
732c76ae52dSmrg
733c76ae52dSmrg    i = 0;
734c76ae52dSmrg    while (i < len)
735c76ae52dSmrg    {
736c76ae52dSmrg	start = i;
737c76ae52dSmrg	if (((XftFontInt *) glyphs[i].font)->format)
738c76ae52dSmrg	{
739c76ae52dSmrg	    Picture	src;
740c76ae52dSmrg	    while (i < len && ((XftFontInt *) glyphs[i].font)->format)
741c76ae52dSmrg		i++;
742c76ae52dSmrg	    if (_XftDrawRenderPrepare (draw) &&
743c76ae52dSmrg		(src = XftDrawSrcPicture (draw, color)))
744c76ae52dSmrg	    {
745c76ae52dSmrg		XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color),
746c76ae52dSmrg					src, draw->render.pict,
747c76ae52dSmrg					0, 0, glyphs + start , i - start);
748c76ae52dSmrg	    }
749c76ae52dSmrg	}
750c76ae52dSmrg	else
751c76ae52dSmrg	{
752c76ae52dSmrg	    while (i < len && !((XftFontInt *) glyphs[i].font)->format)
753c76ae52dSmrg		i++;
754c76ae52dSmrg	    if (_XftDrawCorePrepare (draw, color))
755c76ae52dSmrg		XftGlyphFontSpecCore (draw, color, glyphs + start, i - start);
756c76ae52dSmrg	}
757c76ae52dSmrg    }
758c76ae52dSmrg}
759c76ae52dSmrg
760c76ae52dSmrg_X_EXPORT void
761c76ae52dSmrgXftDrawCharSpec (XftDraw		*draw,
762c76ae52dSmrg		 _Xconst XftColor	*color,
763c76ae52dSmrg		 XftFont		*pub,
764c76ae52dSmrg		 _Xconst XftCharSpec	*chars,
765c76ae52dSmrg		 int			len)
766c76ae52dSmrg{
767c76ae52dSmrg    XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
768c76ae52dSmrg    int		    i;
769c76ae52dSmrg
770de3c0529Smrg    if (len <= 0)
771de3c0529Smrg	return;
772de3c0529Smrg
773c76ae52dSmrg    if (len <= NUM_LOCAL)
774c76ae52dSmrg	glyphs = glyphs_local;
775c76ae52dSmrg    else
776c76ae52dSmrg    {
777de3c0529Smrg	glyphs = AllocGlyphSpecArray (len);
778c76ae52dSmrg	if (!glyphs)
779c76ae52dSmrg	    return;
780c76ae52dSmrg    }
781c76ae52dSmrg    for (i = 0; i < len; i++)
782c76ae52dSmrg    {
783c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4);
784c76ae52dSmrg	glyphs[i].x = chars[i].x;
785c76ae52dSmrg	glyphs[i].y = chars[i].y;
786c76ae52dSmrg    }
787c76ae52dSmrg
788c76ae52dSmrg    XftDrawGlyphSpec (draw, color, pub, glyphs, len);
789c76ae52dSmrg    if (glyphs != glyphs_local)
790c76ae52dSmrg	free (glyphs);
791c76ae52dSmrg}
792c76ae52dSmrg
793c76ae52dSmrg_X_EXPORT void
794c76ae52dSmrgXftDrawCharFontSpec (XftDraw			*draw,
795c76ae52dSmrg		     _Xconst XftColor		*color,
796c76ae52dSmrg		     _Xconst XftCharFontSpec	*chars,
797c76ae52dSmrg		     int			len)
798c76ae52dSmrg{
799c76ae52dSmrg    XftGlyphFontSpec	*glyphs, glyphs_local[NUM_LOCAL];
800c76ae52dSmrg    int			i;
801c76ae52dSmrg
802de3c0529Smrg    if (len <= 0)
803de3c0529Smrg	return;
804de3c0529Smrg
805c76ae52dSmrg    if (len <= NUM_LOCAL)
806c76ae52dSmrg	glyphs = glyphs_local;
807c76ae52dSmrg    else
808c76ae52dSmrg    {
809de3c0529Smrg	glyphs = AllocGlyphFontSpecArray (len);
810c76ae52dSmrg	if (!glyphs)
811c76ae52dSmrg	    return;
812c76ae52dSmrg    }
813c76ae52dSmrg    for (i = 0; i < len; i++)
814c76ae52dSmrg    {
815c76ae52dSmrg	glyphs[i].font = chars[i].font;
816c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4);
817c76ae52dSmrg	glyphs[i].x = chars[i].x;
818c76ae52dSmrg	glyphs[i].y = chars[i].y;
819c76ae52dSmrg    }
820c76ae52dSmrg
821c76ae52dSmrg    XftDrawGlyphFontSpec (draw, color, glyphs, len);
822c76ae52dSmrg    if (glyphs != glyphs_local)
823c76ae52dSmrg	free (glyphs);
824c76ae52dSmrg}
825c76ae52dSmrg
826c76ae52dSmrg_X_EXPORT void
827c76ae52dSmrgXftDrawRect (XftDraw		*draw,
828c76ae52dSmrg	     _Xconst XftColor	*color,
8292836776bSmrg	     int		x,
830c76ae52dSmrg	     int		y,
831c76ae52dSmrg	     unsigned int	width,
832c76ae52dSmrg	     unsigned int	height)
833c76ae52dSmrg{
834c76ae52dSmrg    if (_XftDrawRenderPrepare (draw))
835c76ae52dSmrg    {
836c76ae52dSmrg	XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict,
837c76ae52dSmrg			      &color->color, x, y, width, height);
838c76ae52dSmrg    }
839c76ae52dSmrg    else if (_XftDrawCorePrepare (draw, color))
840c76ae52dSmrg    {
8410d590c07Smrg	/* note: not XftRectCore() */
8420d590c07Smrg	XSetForeground (draw->dpy, draw->core.gc, color->pixel);
8430d590c07Smrg	XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
8440d590c07Smrg			x, y, width, height);
845c76ae52dSmrg    }
846c76ae52dSmrg}
847c76ae52dSmrg
848c76ae52dSmrg_X_EXPORT Bool
849c76ae52dSmrgXftDrawSetClip (XftDraw	*draw,
850c76ae52dSmrg		Region	r)
851c76ae52dSmrg{
8520d590c07Smrg    Region			n = NULL;
853c76ae52dSmrg
854c76ae52dSmrg    /*
855c76ae52dSmrg     * Check for quick exits
856c76ae52dSmrg     */
857c76ae52dSmrg    if (!r && draw->clip_type == XftClipTypeNone)
858c76ae52dSmrg	return True;
8592836776bSmrg
8602836776bSmrg    if (r &&
8612836776bSmrg	draw->clip_type == XftClipTypeRegion &&
862c76ae52dSmrg	XEqualRegion (r, draw->clip.region))
863c76ae52dSmrg    {
864c76ae52dSmrg	return True;
865c76ae52dSmrg    }
866c76ae52dSmrg
867c76ae52dSmrg    /*
868c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
869c76ae52dSmrg     */
870c76ae52dSmrg    if (r)
871c76ae52dSmrg    {
872c76ae52dSmrg	n = XCreateRegion ();
873c76ae52dSmrg	if (n)
874c76ae52dSmrg	{
875c76ae52dSmrg	    if (!XUnionRegion (n, r, n))
876c76ae52dSmrg	    {
877c76ae52dSmrg		XDestroyRegion (n);
878c76ae52dSmrg		return False;
879c76ae52dSmrg	    }
880c76ae52dSmrg	}
881c76ae52dSmrg    }
882c76ae52dSmrg
883c76ae52dSmrg    /*
884c76ae52dSmrg     * Destroy existing clip
885c76ae52dSmrg     */
886c76ae52dSmrg    switch (draw->clip_type) {
887c76ae52dSmrg    case XftClipTypeRegion:
888c76ae52dSmrg	XDestroyRegion (draw->clip.region);
889c76ae52dSmrg	break;
890c76ae52dSmrg    case XftClipTypeRectangles:
891c76ae52dSmrg	free (draw->clip.rect);
892c76ae52dSmrg	break;
893c76ae52dSmrg    case XftClipTypeNone:
894c76ae52dSmrg	break;
895c76ae52dSmrg    }
8962836776bSmrg
897c76ae52dSmrg    /*
898c76ae52dSmrg     * Set the clip
899c76ae52dSmrg     */
900c76ae52dSmrg    if (n)
901c76ae52dSmrg    {
902c76ae52dSmrg	draw->clip_type = XftClipTypeRegion;
903c76ae52dSmrg	draw->clip.region = n;
904c76ae52dSmrg    }
905c76ae52dSmrg    else
906c76ae52dSmrg    {
907c76ae52dSmrg	draw->clip_type = XftClipTypeNone;
908c76ae52dSmrg    }
909c76ae52dSmrg    /*
910c76ae52dSmrg     * Apply new clip to existing objects
911c76ae52dSmrg     */
912c76ae52dSmrg    if (draw->render.pict)
913c76ae52dSmrg    {
914c76ae52dSmrg	if (n)
915c76ae52dSmrg	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n);
916c76ae52dSmrg	else
917c76ae52dSmrg	{
918c76ae52dSmrg	    XRenderPictureAttributes	pa;
919c76ae52dSmrg	    pa.clip_mask = None;
920c76ae52dSmrg	    XRenderChangePicture (draw->dpy, draw->render.pict,
921c76ae52dSmrg				  CPClipMask, &pa);
922c76ae52dSmrg	}
923c76ae52dSmrg    }
924c76ae52dSmrg    if (draw->core.gc)
925c76ae52dSmrg    {
926c76ae52dSmrg	if (n)
927c76ae52dSmrg	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
928c76ae52dSmrg	else
929c76ae52dSmrg	    XSetClipMask (draw->dpy, draw->core.gc, None);
930c76ae52dSmrg    }
931c76ae52dSmrg    return True;
932c76ae52dSmrg}
933c76ae52dSmrg
934c76ae52dSmrg_X_EXPORT Bool
935c76ae52dSmrgXftDrawSetClipRectangles (XftDraw		*draw,
936c76ae52dSmrg			  int			xOrigin,
937c76ae52dSmrg			  int			yOrigin,
938c76ae52dSmrg			  _Xconst XRectangle	*rects,
939c76ae52dSmrg			  int			n)
940c76ae52dSmrg{
9410d590c07Smrg    XftClipRect	*new = NULL;
942c76ae52dSmrg
943c76ae52dSmrg    /*
944c76ae52dSmrg     * Check for quick exit
945c76ae52dSmrg     */
946c76ae52dSmrg    if (draw->clip_type == XftClipTypeRectangles &&
947c76ae52dSmrg	draw->clip.rect->n == n &&
948c76ae52dSmrg	(n == 0 || (draw->clip.rect->xOrigin == xOrigin &&
949c76ae52dSmrg		    draw->clip.rect->yOrigin == yOrigin)) &&
95084febdacSmrg	!memcmp (XftClipRects (draw->clip.rect), rects, (size_t)n * sizeof (XRectangle)))
951c76ae52dSmrg    {
952c76ae52dSmrg	return True;
953c76ae52dSmrg    }
954c76ae52dSmrg
955c76ae52dSmrg    /*
956c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
957c76ae52dSmrg     */
95884febdacSmrg    new = malloc (sizeof (XftClipRect) + (size_t)n * sizeof (XRectangle));
959c76ae52dSmrg    if (!new)
960c76ae52dSmrg	return False;
961c76ae52dSmrg
962c76ae52dSmrg    new->n = n;
963c76ae52dSmrg    new->xOrigin = xOrigin;
964c76ae52dSmrg    new->yOrigin = yOrigin;
96584febdacSmrg    memcpy (XftClipRects (new), rects, (size_t)n * sizeof (XRectangle));
966c76ae52dSmrg
967c76ae52dSmrg    /*
968c76ae52dSmrg     * Destroy existing clip
969c76ae52dSmrg     */
970c76ae52dSmrg    switch (draw->clip_type) {
971c76ae52dSmrg    case XftClipTypeRegion:
972c76ae52dSmrg	XDestroyRegion (draw->clip.region);
973c76ae52dSmrg	break;
974c76ae52dSmrg    case XftClipTypeRectangles:
975c76ae52dSmrg	free (draw->clip.rect);
976c76ae52dSmrg	break;
977c76ae52dSmrg    case XftClipTypeNone:
978c76ae52dSmrg	break;
979c76ae52dSmrg    }
9802836776bSmrg
981c76ae52dSmrg    /*
982c76ae52dSmrg     * Set the clip
983c76ae52dSmrg     */
984c76ae52dSmrg    draw->clip_type = XftClipTypeRectangles;
985c76ae52dSmrg    draw->clip.rect = new;
986c76ae52dSmrg    /*
987c76ae52dSmrg     * Apply new clip to existing objects
988c76ae52dSmrg     */
989c76ae52dSmrg    if (draw->render.pict)
990c76ae52dSmrg    {
991c76ae52dSmrg	XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
992c76ae52dSmrg					 new->xOrigin,
993c76ae52dSmrg					 new->yOrigin,
994c76ae52dSmrg					 XftClipRects(new),
995c76ae52dSmrg					 new->n);
996c76ae52dSmrg    }
997c76ae52dSmrg    if (draw->core.gc)
998c76ae52dSmrg    {
999c76ae52dSmrg	XSetClipRectangles (draw->dpy, draw->core.gc,
1000c76ae52dSmrg			    new->xOrigin,
1001c76ae52dSmrg			    new->yOrigin,
1002c76ae52dSmrg			    XftClipRects (new),
1003c76ae52dSmrg			    new->n,
1004c76ae52dSmrg			    Unsorted);
1005c76ae52dSmrg    }
1006c76ae52dSmrg    return True;
1007c76ae52dSmrg}
1008c76ae52dSmrg
1009c76ae52dSmrg_X_EXPORT void
1010c76ae52dSmrgXftDrawSetSubwindowMode (XftDraw *draw, int mode)
1011c76ae52dSmrg{
1012c76ae52dSmrg    if (mode == draw->subwindow_mode)
1013c76ae52dSmrg	return;
1014c76ae52dSmrg    draw->subwindow_mode = mode;
1015c76ae52dSmrg    if (draw->render.pict)
1016c76ae52dSmrg    {
1017c76ae52dSmrg	XRenderPictureAttributes    pa;
1018c76ae52dSmrg
1019c76ae52dSmrg	pa.subwindow_mode = mode;
10202836776bSmrg	XRenderChangePicture (draw->dpy, draw->render.pict,
1021c76ae52dSmrg			      CPSubwindowMode, &pa);
1022c76ae52dSmrg    }
1023c76ae52dSmrg    if (draw->core.gc)
1024c76ae52dSmrg	XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
1025c76ae52dSmrg}
1026