xftdraw.c revision 0d590c07
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;
91c76ae52dSmrg	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;
107c76ae52dSmrg
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;
138c76ae52dSmrg
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
304c76ae52dSmrg    if (!info)
305c76ae52dSmrg	return 0;
306c76ae52dSmrg
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    {
325c76ae52dSmrg	if (info->colors[i].pict &&
326c76ae52dSmrg	    info->colors[i].screen == draw->screen &&
327c76ae52dSmrg	    !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;
336c76ae52dSmrg    /*
337c76ae52dSmrg     * Recreate if it was for the wrong screen
338c76ae52dSmrg     */
339c76ae52dSmrg    if (info->colors[i].screen != draw->screen && info->colors[i].pict)
340c76ae52dSmrg    {
341c76ae52dSmrg	XRenderFreePicture (dpy, info->colors[i].pict);
342c76ae52dSmrg	info->colors[i].pict = 0;
343c76ae52dSmrg    }
344c76ae52dSmrg    /*
345c76ae52dSmrg     * Create picture if necessary
346c76ae52dSmrg     */
347c76ae52dSmrg    if (!info->colors[i].pict)
348c76ae52dSmrg    {
349c76ae52dSmrg	Pixmap			    pix;
350c76ae52dSmrg        XRenderPictureAttributes    pa;
351c76ae52dSmrg
352c76ae52dSmrg	pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1,
353c76ae52dSmrg			     info->solidFormat->depth);
354c76ae52dSmrg	pa.repeat = True;
355c76ae52dSmrg	info->colors[i].pict = XRenderCreatePicture (draw->dpy,
356c76ae52dSmrg						     pix,
357c76ae52dSmrg						     info->solidFormat,
358c76ae52dSmrg						     CPRepeat, &pa);
359c76ae52dSmrg	XFreePixmap (dpy, pix);
360c76ae52dSmrg    }
361c76ae52dSmrg    /*
362c76ae52dSmrg     * Set to the new color
363c76ae52dSmrg     */
364c76ae52dSmrg    info->colors[i].color = color->color;
365c76ae52dSmrg    info->colors[i].screen = draw->screen;
366c76ae52dSmrg    XRenderFillRectangle (dpy, PictOpSrc,
367c76ae52dSmrg			  info->colors[i].pict,
368c76ae52dSmrg			  &color->color, 0, 0, 1, 1);
369c76ae52dSmrg    return info->colors[i].pict;
370c76ae52dSmrg}
371c76ae52dSmrg
372c76ae52dSmrgstatic int
373c76ae52dSmrg_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color)
374c76ae52dSmrg{
375c76ae52dSmrg    if (draw->visual || draw->depth != 1)
376c76ae52dSmrg	return PictOpOver;
377c76ae52dSmrg    if (color->color.alpha >= 0x8000)
378c76ae52dSmrg	return PictOpOver;
379c76ae52dSmrg    return PictOpOutReverse;
380c76ae52dSmrg}
381c76ae52dSmrg
382c76ae52dSmrgstatic FcBool
383c76ae52dSmrg_XftDrawRenderPrepare (XftDraw	*draw)
384c76ae52dSmrg{
385c76ae52dSmrg    if (!draw->render.pict)
386c76ae52dSmrg    {
387c76ae52dSmrg	XRenderPictFormat	    *format;
388c76ae52dSmrg	XRenderPictureAttributes    pa;
389c76ae52dSmrg	unsigned long		    mask = 0;
390c76ae52dSmrg
391c76ae52dSmrg	format = _XftDrawFormat (draw);
392c76ae52dSmrg	if (!format)
393c76ae52dSmrg	    return FcFalse;
394c76ae52dSmrg
395c76ae52dSmrg	if (draw->subwindow_mode == IncludeInferiors)
396c76ae52dSmrg	{
397c76ae52dSmrg	    pa.subwindow_mode = IncludeInferiors;
398c76ae52dSmrg	    mask |= CPSubwindowMode;
399c76ae52dSmrg	}
400c76ae52dSmrg	draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable,
401c76ae52dSmrg						  format, mask, &pa);
402c76ae52dSmrg	if (!draw->render.pict)
403c76ae52dSmrg	    return FcFalse;
404c76ae52dSmrg	switch (draw->clip_type) {
405c76ae52dSmrg	case XftClipTypeRegion:
406c76ae52dSmrg	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
407c76ae52dSmrg					 draw->clip.region);
408c76ae52dSmrg	    break;
409c76ae52dSmrg	case XftClipTypeRectangles:
410c76ae52dSmrg	    XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
411c76ae52dSmrg					     draw->clip.rect->xOrigin,
412c76ae52dSmrg					     draw->clip.rect->yOrigin,
413c76ae52dSmrg					     XftClipRects(draw->clip.rect),
414c76ae52dSmrg					     draw->clip.rect->n);
415c76ae52dSmrg	    break;
416c76ae52dSmrg	case XftClipTypeNone:
417c76ae52dSmrg	    break;
418c76ae52dSmrg	}
419c76ae52dSmrg    }
420c76ae52dSmrg    return FcTrue;
421c76ae52dSmrg}
422c76ae52dSmrg
423c76ae52dSmrgstatic FcBool
424c76ae52dSmrg_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color)
425c76ae52dSmrg{
426c76ae52dSmrg    if (!draw->core.gc)
427c76ae52dSmrg    {
428c76ae52dSmrg	XGCValues	gcv;
429c76ae52dSmrg	unsigned long	mask = 0;
430c76ae52dSmrg	if (draw->subwindow_mode == IncludeInferiors)
431c76ae52dSmrg	{
432c76ae52dSmrg	    gcv.subwindow_mode = IncludeInferiors;
433c76ae52dSmrg	    mask |= GCSubwindowMode;
434c76ae52dSmrg	}
435c76ae52dSmrg	draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv);
436c76ae52dSmrg	if (!draw->core.gc)
437c76ae52dSmrg	    return FcFalse;
438c76ae52dSmrg	switch (draw->clip_type) {
439c76ae52dSmrg	case XftClipTypeRegion:
440c76ae52dSmrg	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
441c76ae52dSmrg	    break;
442c76ae52dSmrg	case XftClipTypeRectangles:
443c76ae52dSmrg	    XSetClipRectangles (draw->dpy, draw->core.gc,
444c76ae52dSmrg				draw->clip.rect->xOrigin,
445c76ae52dSmrg				draw->clip.rect->yOrigin,
446c76ae52dSmrg				XftClipRects (draw->clip.rect),
447c76ae52dSmrg				draw->clip.rect->n,
448c76ae52dSmrg				Unsorted);
449c76ae52dSmrg	    break;
450c76ae52dSmrg	case XftClipTypeNone:
451c76ae52dSmrg	    break;
452c76ae52dSmrg	}
453c76ae52dSmrg    }
454c76ae52dSmrg    XSetForeground (draw->dpy, draw->core.gc, color->pixel);
455c76ae52dSmrg    return FcTrue;
456c76ae52dSmrg}
457c76ae52dSmrg
458c76ae52dSmrg_X_EXPORT Picture
459c76ae52dSmrgXftDrawPicture (XftDraw *draw)
460c76ae52dSmrg{
461c76ae52dSmrg    if (!_XftDrawRenderPrepare (draw))
462c76ae52dSmrg	return 0;
463c76ae52dSmrg    return draw->render.pict;
464c76ae52dSmrg}
465c76ae52dSmrg
466c76ae52dSmrg#define NUM_LOCAL   1024
467c76ae52dSmrg
468c76ae52dSmrg_X_EXPORT void
469c76ae52dSmrgXftDrawGlyphs (XftDraw		*draw,
470c76ae52dSmrg	       _Xconst XftColor	*color,
471c76ae52dSmrg	       XftFont		*pub,
472c76ae52dSmrg	       int		x,
473c76ae52dSmrg	       int		y,
474c76ae52dSmrg	       _Xconst FT_UInt	*glyphs,
475c76ae52dSmrg	       int		nglyphs)
476c76ae52dSmrg{
477c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
478c76ae52dSmrg
479c76ae52dSmrg    if (font->format)
480c76ae52dSmrg    {
481c76ae52dSmrg	Picture	    src;
482c76ae52dSmrg
483c76ae52dSmrg	if (_XftDrawRenderPrepare (draw) &&
484c76ae52dSmrg	    (src = XftDrawSrcPicture (draw, color)))
485c76ae52dSmrg	    XftGlyphRender (draw->dpy, _XftDrawOp (draw, color),
486c76ae52dSmrg			     src, pub, draw->render.pict,
487c76ae52dSmrg			     0, 0, x, y, glyphs, nglyphs);
488c76ae52dSmrg    }
489c76ae52dSmrg    else
490c76ae52dSmrg    {
491c76ae52dSmrg	if (_XftDrawCorePrepare (draw, color))
492c76ae52dSmrg	    XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs);
493c76ae52dSmrg    }
494c76ae52dSmrg}
495c76ae52dSmrg
496c76ae52dSmrg_X_EXPORT void
497c76ae52dSmrgXftDrawString8 (XftDraw		    *draw,
498c76ae52dSmrg		_Xconst XftColor    *color,
499c76ae52dSmrg		XftFont		    *pub,
500c76ae52dSmrg		int		    x,
501c76ae52dSmrg		int		    y,
502c76ae52dSmrg		_Xconst FcChar8	    *string,
503c76ae52dSmrg		int		    len)
504c76ae52dSmrg{
505c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
506c76ae52dSmrg    int		    i;
507c76ae52dSmrg
508c76ae52dSmrg    if (XftDebug () & XFT_DBG_DRAW)
509c76ae52dSmrg	printf ("DrawString \"%*.*s\"\n", len, len, string);
510c76ae52dSmrg
511c76ae52dSmrg    if (len <= NUM_LOCAL)
512c76ae52dSmrg	glyphs = glyphs_local;
513c76ae52dSmrg    else
514c76ae52dSmrg    {
515c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
516c76ae52dSmrg	if (!glyphs)
517c76ae52dSmrg	    return;
518c76ae52dSmrg    }
519c76ae52dSmrg    for (i = 0; i < len; i++)
520c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
521c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
522c76ae52dSmrg    if (glyphs != glyphs_local)
523c76ae52dSmrg	free (glyphs);
524c76ae52dSmrg}
525c76ae52dSmrg
526c76ae52dSmrg_X_EXPORT void
527c76ae52dSmrgXftDrawString16 (XftDraw	    *draw,
528c76ae52dSmrg		 _Xconst XftColor   *color,
529c76ae52dSmrg		 XftFont	    *pub,
530c76ae52dSmrg		 int		    x,
531c76ae52dSmrg		 int		    y,
532c76ae52dSmrg		 _Xconst FcChar16   *string,
533c76ae52dSmrg		 int		    len)
534c76ae52dSmrg{
535c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
536c76ae52dSmrg    int		    i;
537c76ae52dSmrg
538c76ae52dSmrg    if (len <= NUM_LOCAL)
539c76ae52dSmrg	glyphs = glyphs_local;
540c76ae52dSmrg    else
541c76ae52dSmrg    {
542c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
543c76ae52dSmrg	if (!glyphs)
544c76ae52dSmrg	    return;
545c76ae52dSmrg    }
546c76ae52dSmrg    for (i = 0; i < len; i++)
547c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
548c76ae52dSmrg
549c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
550c76ae52dSmrg    if (glyphs != glyphs_local)
551c76ae52dSmrg	free (glyphs);
552c76ae52dSmrg}
553c76ae52dSmrg
554c76ae52dSmrg_X_EXPORT void
555c76ae52dSmrgXftDrawString32 (XftDraw	    *draw,
556c76ae52dSmrg		 _Xconst XftColor   *color,
557c76ae52dSmrg		 XftFont	    *pub,
558c76ae52dSmrg		 int		    x,
559c76ae52dSmrg		 int		    y,
560c76ae52dSmrg		 _Xconst FcChar32   *string,
561c76ae52dSmrg		 int		    len)
562c76ae52dSmrg{
563c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
564c76ae52dSmrg    int		    i;
565c76ae52dSmrg
566c76ae52dSmrg    if (len <= NUM_LOCAL)
567c76ae52dSmrg	glyphs = glyphs_local;
568c76ae52dSmrg    else
569c76ae52dSmrg    {
570c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
571c76ae52dSmrg	if (!glyphs)
572c76ae52dSmrg	    return;
573c76ae52dSmrg    }
574c76ae52dSmrg    for (i = 0; i < len; i++)
575c76ae52dSmrg	glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
576c76ae52dSmrg
577c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
578c76ae52dSmrg    if (glyphs != glyphs_local)
579c76ae52dSmrg	free (glyphs);
580c76ae52dSmrg}
581c76ae52dSmrg
582c76ae52dSmrg_X_EXPORT void
583c76ae52dSmrgXftDrawStringUtf8 (XftDraw	    *draw,
584c76ae52dSmrg		   _Xconst XftColor *color,
585c76ae52dSmrg		   XftFont	    *pub,
586c76ae52dSmrg		   int		    x,
587c76ae52dSmrg		   int		    y,
588c76ae52dSmrg		   _Xconst FcChar8  *string,
589c76ae52dSmrg		   int		    len)
590c76ae52dSmrg{
591c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
592c76ae52dSmrg    FcChar32	    ucs4;
593c76ae52dSmrg    int		    i;
594c76ae52dSmrg    int		    l;
595c76ae52dSmrg    int		    size;
596c76ae52dSmrg
597c76ae52dSmrg    i = 0;
598c76ae52dSmrg    glyphs = glyphs_local;
599c76ae52dSmrg    size = NUM_LOCAL;
600c76ae52dSmrg    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
601c76ae52dSmrg    {
602c76ae52dSmrg	if (i == size)
603c76ae52dSmrg	{
604c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
605c76ae52dSmrg	    if (!glyphs_new)
606c76ae52dSmrg	    {
607c76ae52dSmrg		if (glyphs != glyphs_local)
608c76ae52dSmrg		    free (glyphs);
609c76ae52dSmrg		return;
610c76ae52dSmrg	    }
611c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
612c76ae52dSmrg	    size *= 2;
613c76ae52dSmrg	    if (glyphs != glyphs_local)
614c76ae52dSmrg		free (glyphs);
615c76ae52dSmrg	    glyphs = glyphs_new;
616c76ae52dSmrg	}
617c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
618c76ae52dSmrg	string += l;
619c76ae52dSmrg	len -= l;
620c76ae52dSmrg    }
621c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
622c76ae52dSmrg    if (glyphs != glyphs_local)
623c76ae52dSmrg	free (glyphs);
624c76ae52dSmrg}
625c76ae52dSmrg
626c76ae52dSmrg_X_EXPORT void
627c76ae52dSmrgXftDrawStringUtf16 (XftDraw		*draw,
628c76ae52dSmrg		    _Xconst XftColor	*color,
629c76ae52dSmrg		    XftFont		*pub,
630c76ae52dSmrg		    int			x,
631c76ae52dSmrg		    int			y,
632c76ae52dSmrg		    _Xconst FcChar8	*string,
633c76ae52dSmrg		    FcEndian		endian,
634c76ae52dSmrg		    int			len)
635c76ae52dSmrg{
636c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
637c76ae52dSmrg    FcChar32	    ucs4;
638c76ae52dSmrg    int		    i;
639c76ae52dSmrg    int		    l;
640c76ae52dSmrg    int		    size;
641c76ae52dSmrg
642c76ae52dSmrg    i = 0;
643c76ae52dSmrg    glyphs = glyphs_local;
644c76ae52dSmrg    size = NUM_LOCAL;
645c76ae52dSmrg    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
646c76ae52dSmrg    {
647c76ae52dSmrg	if (i == size)
648c76ae52dSmrg	{
649c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
650c76ae52dSmrg	    if (!glyphs_new)
651c76ae52dSmrg	    {
652c76ae52dSmrg		if (glyphs != glyphs_local)
653c76ae52dSmrg		    free (glyphs);
654c76ae52dSmrg		return;
655c76ae52dSmrg	    }
656c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
657c76ae52dSmrg	    size *= 2;
658c76ae52dSmrg	    if (glyphs != glyphs_local)
659c76ae52dSmrg		free (glyphs);
660c76ae52dSmrg	    glyphs = glyphs_new;
661c76ae52dSmrg	}
662c76ae52dSmrg	glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
663c76ae52dSmrg	string += l;
664c76ae52dSmrg	len -= l;
665c76ae52dSmrg    }
666c76ae52dSmrg    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
667c76ae52dSmrg    if (glyphs != glyphs_local)
668c76ae52dSmrg	free (glyphs);
669c76ae52dSmrg}
670c76ae52dSmrg
671c76ae52dSmrg_X_EXPORT void
672c76ae52dSmrgXftDrawGlyphSpec (XftDraw		*draw,
673c76ae52dSmrg		  _Xconst XftColor	*color,
674c76ae52dSmrg		  XftFont		*pub,
675c76ae52dSmrg		  _Xconst XftGlyphSpec	*glyphs,
676c76ae52dSmrg		  int			len)
677c76ae52dSmrg{
678c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
679c76ae52dSmrg
680c76ae52dSmrg    if (font->format)
681c76ae52dSmrg    {
682c76ae52dSmrg	Picture	src;
683c76ae52dSmrg
684c76ae52dSmrg	if (_XftDrawRenderPrepare (draw) &&
685c76ae52dSmrg	    (src = XftDrawSrcPicture (draw, color)))
686c76ae52dSmrg	{
687c76ae52dSmrg	    XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color),
688c76ae52dSmrg				src, pub, draw->render.pict,
689c76ae52dSmrg				0, 0, glyphs, len);
690c76ae52dSmrg	}
691c76ae52dSmrg    }
692c76ae52dSmrg    else
693c76ae52dSmrg    {
694c76ae52dSmrg	if (_XftDrawCorePrepare (draw, color))
695c76ae52dSmrg	    XftGlyphSpecCore (draw, color, pub, glyphs, len);
696c76ae52dSmrg    }
697c76ae52dSmrg}
698c76ae52dSmrg
699c76ae52dSmrg_X_EXPORT void
700c76ae52dSmrgXftDrawGlyphFontSpec (XftDraw			*draw,
701c76ae52dSmrg		      _Xconst XftColor		*color,
702c76ae52dSmrg		      _Xconst XftGlyphFontSpec	*glyphs,
703c76ae52dSmrg		      int			len)
704c76ae52dSmrg{
705c76ae52dSmrg    int		i;
706c76ae52dSmrg    int		start;
707c76ae52dSmrg
708c76ae52dSmrg    i = 0;
709c76ae52dSmrg    while (i < len)
710c76ae52dSmrg    {
711c76ae52dSmrg	start = i;
712c76ae52dSmrg	if (((XftFontInt *) glyphs[i].font)->format)
713c76ae52dSmrg	{
714c76ae52dSmrg	    Picture	src;
715c76ae52dSmrg	    while (i < len && ((XftFontInt *) glyphs[i].font)->format)
716c76ae52dSmrg		i++;
717c76ae52dSmrg	    if (_XftDrawRenderPrepare (draw) &&
718c76ae52dSmrg		(src = XftDrawSrcPicture (draw, color)))
719c76ae52dSmrg	    {
720c76ae52dSmrg		XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color),
721c76ae52dSmrg					src, draw->render.pict,
722c76ae52dSmrg					0, 0, glyphs + start , i - start);
723c76ae52dSmrg	    }
724c76ae52dSmrg	}
725c76ae52dSmrg	else
726c76ae52dSmrg	{
727c76ae52dSmrg	    while (i < len && !((XftFontInt *) glyphs[i].font)->format)
728c76ae52dSmrg		i++;
729c76ae52dSmrg	    if (_XftDrawCorePrepare (draw, color))
730c76ae52dSmrg		XftGlyphFontSpecCore (draw, color, glyphs + start, i - start);
731c76ae52dSmrg	}
732c76ae52dSmrg    }
733c76ae52dSmrg}
734c76ae52dSmrg
735c76ae52dSmrg_X_EXPORT void
736c76ae52dSmrgXftDrawCharSpec (XftDraw		*draw,
737c76ae52dSmrg		 _Xconst XftColor	*color,
738c76ae52dSmrg		 XftFont		*pub,
739c76ae52dSmrg		 _Xconst XftCharSpec	*chars,
740c76ae52dSmrg		 int			len)
741c76ae52dSmrg{
742c76ae52dSmrg    XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
743c76ae52dSmrg    int		    i;
744c76ae52dSmrg
745c76ae52dSmrg    if (len <= NUM_LOCAL)
746c76ae52dSmrg	glyphs = glyphs_local;
747c76ae52dSmrg    else
748c76ae52dSmrg    {
749c76ae52dSmrg	glyphs = malloc (len * sizeof (XftGlyphSpec));
750c76ae52dSmrg	if (!glyphs)
751c76ae52dSmrg	    return;
752c76ae52dSmrg    }
753c76ae52dSmrg    for (i = 0; i < len; i++)
754c76ae52dSmrg    {
755c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4);
756c76ae52dSmrg	glyphs[i].x = chars[i].x;
757c76ae52dSmrg	glyphs[i].y = chars[i].y;
758c76ae52dSmrg    }
759c76ae52dSmrg
760c76ae52dSmrg    XftDrawGlyphSpec (draw, color, pub, glyphs, len);
761c76ae52dSmrg    if (glyphs != glyphs_local)
762c76ae52dSmrg	free (glyphs);
763c76ae52dSmrg}
764c76ae52dSmrg
765c76ae52dSmrg_X_EXPORT void
766c76ae52dSmrgXftDrawCharFontSpec (XftDraw			*draw,
767c76ae52dSmrg		     _Xconst XftColor		*color,
768c76ae52dSmrg		     _Xconst XftCharFontSpec	*chars,
769c76ae52dSmrg		     int			len)
770c76ae52dSmrg{
771c76ae52dSmrg    XftGlyphFontSpec	*glyphs, glyphs_local[NUM_LOCAL];
772c76ae52dSmrg    int			i;
773c76ae52dSmrg
774c76ae52dSmrg    if (len <= NUM_LOCAL)
775c76ae52dSmrg	glyphs = glyphs_local;
776c76ae52dSmrg    else
777c76ae52dSmrg    {
778c76ae52dSmrg	glyphs = malloc (len * sizeof (XftGlyphFontSpec));
779c76ae52dSmrg	if (!glyphs)
780c76ae52dSmrg	    return;
781c76ae52dSmrg    }
782c76ae52dSmrg    for (i = 0; i < len; i++)
783c76ae52dSmrg    {
784c76ae52dSmrg	glyphs[i].font = chars[i].font;
785c76ae52dSmrg	glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4);
786c76ae52dSmrg	glyphs[i].x = chars[i].x;
787c76ae52dSmrg	glyphs[i].y = chars[i].y;
788c76ae52dSmrg    }
789c76ae52dSmrg
790c76ae52dSmrg    XftDrawGlyphFontSpec (draw, color, glyphs, len);
791c76ae52dSmrg    if (glyphs != glyphs_local)
792c76ae52dSmrg	free (glyphs);
793c76ae52dSmrg}
794c76ae52dSmrg
795c76ae52dSmrg_X_EXPORT void
796c76ae52dSmrgXftDrawRect (XftDraw		*draw,
797c76ae52dSmrg	     _Xconst XftColor	*color,
798c76ae52dSmrg	     int		x,
799c76ae52dSmrg	     int		y,
800c76ae52dSmrg	     unsigned int	width,
801c76ae52dSmrg	     unsigned int	height)
802c76ae52dSmrg{
803c76ae52dSmrg    if (_XftDrawRenderPrepare (draw))
804c76ae52dSmrg    {
805c76ae52dSmrg	XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict,
806c76ae52dSmrg			      &color->color, x, y, width, height);
807c76ae52dSmrg    }
808c76ae52dSmrg    else if (_XftDrawCorePrepare (draw, color))
809c76ae52dSmrg    {
8100d590c07Smrg	/* note: not XftRectCore() */
8110d590c07Smrg	XSetForeground (draw->dpy, draw->core.gc, color->pixel);
8120d590c07Smrg	XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
8130d590c07Smrg			x, y, width, height);
814c76ae52dSmrg    }
815c76ae52dSmrg}
816c76ae52dSmrg
817c76ae52dSmrg_X_EXPORT Bool
818c76ae52dSmrgXftDrawSetClip (XftDraw	*draw,
819c76ae52dSmrg		Region	r)
820c76ae52dSmrg{
8210d590c07Smrg    Region			n = NULL;
822c76ae52dSmrg
823c76ae52dSmrg    /*
824c76ae52dSmrg     * Check for quick exits
825c76ae52dSmrg     */
826c76ae52dSmrg    if (!r && draw->clip_type == XftClipTypeNone)
827c76ae52dSmrg	return True;
828c76ae52dSmrg
829c76ae52dSmrg    if (r &&
830c76ae52dSmrg	draw->clip_type == XftClipTypeRegion &&
831c76ae52dSmrg	XEqualRegion (r, draw->clip.region))
832c76ae52dSmrg    {
833c76ae52dSmrg	return True;
834c76ae52dSmrg    }
835c76ae52dSmrg
836c76ae52dSmrg    /*
837c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
838c76ae52dSmrg     */
839c76ae52dSmrg    if (r)
840c76ae52dSmrg    {
841c76ae52dSmrg	n = XCreateRegion ();
842c76ae52dSmrg	if (n)
843c76ae52dSmrg	{
844c76ae52dSmrg	    if (!XUnionRegion (n, r, n))
845c76ae52dSmrg	    {
846c76ae52dSmrg		XDestroyRegion (n);
847c76ae52dSmrg		return False;
848c76ae52dSmrg	    }
849c76ae52dSmrg	}
850c76ae52dSmrg    }
851c76ae52dSmrg
852c76ae52dSmrg    /*
853c76ae52dSmrg     * Destroy existing clip
854c76ae52dSmrg     */
855c76ae52dSmrg    switch (draw->clip_type) {
856c76ae52dSmrg    case XftClipTypeRegion:
857c76ae52dSmrg	XDestroyRegion (draw->clip.region);
858c76ae52dSmrg	break;
859c76ae52dSmrg    case XftClipTypeRectangles:
860c76ae52dSmrg	free (draw->clip.rect);
861c76ae52dSmrg	break;
862c76ae52dSmrg    case XftClipTypeNone:
863c76ae52dSmrg	break;
864c76ae52dSmrg    }
865c76ae52dSmrg
866c76ae52dSmrg    /*
867c76ae52dSmrg     * Set the clip
868c76ae52dSmrg     */
869c76ae52dSmrg    if (n)
870c76ae52dSmrg    {
871c76ae52dSmrg	draw->clip_type = XftClipTypeRegion;
872c76ae52dSmrg	draw->clip.region = n;
873c76ae52dSmrg    }
874c76ae52dSmrg    else
875c76ae52dSmrg    {
876c76ae52dSmrg	draw->clip_type = XftClipTypeNone;
877c76ae52dSmrg    }
878c76ae52dSmrg    /*
879c76ae52dSmrg     * Apply new clip to existing objects
880c76ae52dSmrg     */
881c76ae52dSmrg    if (draw->render.pict)
882c76ae52dSmrg    {
883c76ae52dSmrg	if (n)
884c76ae52dSmrg	    XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n);
885c76ae52dSmrg	else
886c76ae52dSmrg	{
887c76ae52dSmrg	    XRenderPictureAttributes	pa;
888c76ae52dSmrg	    pa.clip_mask = None;
889c76ae52dSmrg	    XRenderChangePicture (draw->dpy, draw->render.pict,
890c76ae52dSmrg				  CPClipMask, &pa);
891c76ae52dSmrg	}
892c76ae52dSmrg    }
893c76ae52dSmrg    if (draw->core.gc)
894c76ae52dSmrg    {
895c76ae52dSmrg	if (n)
896c76ae52dSmrg	    XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
897c76ae52dSmrg	else
898c76ae52dSmrg	    XSetClipMask (draw->dpy, draw->core.gc, None);
899c76ae52dSmrg    }
900c76ae52dSmrg    return True;
901c76ae52dSmrg}
902c76ae52dSmrg
903c76ae52dSmrg_X_EXPORT Bool
904c76ae52dSmrgXftDrawSetClipRectangles (XftDraw		*draw,
905c76ae52dSmrg			  int			xOrigin,
906c76ae52dSmrg			  int			yOrigin,
907c76ae52dSmrg			  _Xconst XRectangle	*rects,
908c76ae52dSmrg			  int			n)
909c76ae52dSmrg{
9100d590c07Smrg    XftClipRect	*new = NULL;
911c76ae52dSmrg
912c76ae52dSmrg    /*
913c76ae52dSmrg     * Check for quick exit
914c76ae52dSmrg     */
915c76ae52dSmrg    if (draw->clip_type == XftClipTypeRectangles &&
916c76ae52dSmrg	draw->clip.rect->n == n &&
917c76ae52dSmrg	(n == 0 || (draw->clip.rect->xOrigin == xOrigin &&
918c76ae52dSmrg		    draw->clip.rect->yOrigin == yOrigin)) &&
919c76ae52dSmrg	!memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle)))
920c76ae52dSmrg    {
921c76ae52dSmrg	return True;
922c76ae52dSmrg    }
923c76ae52dSmrg
924c76ae52dSmrg    /*
925c76ae52dSmrg     * Duplicate the region so future changes can be short circuited
926c76ae52dSmrg     */
927c76ae52dSmrg    new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle));
928c76ae52dSmrg    if (!new)
929c76ae52dSmrg	return False;
930c76ae52dSmrg
931c76ae52dSmrg    new->n = n;
932c76ae52dSmrg    new->xOrigin = xOrigin;
933c76ae52dSmrg    new->yOrigin = yOrigin;
934c76ae52dSmrg    memcpy (XftClipRects (new), rects, n * sizeof (XRectangle));
935c76ae52dSmrg
936c76ae52dSmrg    /*
937c76ae52dSmrg     * Destroy existing clip
938c76ae52dSmrg     */
939c76ae52dSmrg    switch (draw->clip_type) {
940c76ae52dSmrg    case XftClipTypeRegion:
941c76ae52dSmrg	XDestroyRegion (draw->clip.region);
942c76ae52dSmrg	break;
943c76ae52dSmrg    case XftClipTypeRectangles:
944c76ae52dSmrg	free (draw->clip.rect);
945c76ae52dSmrg	break;
946c76ae52dSmrg    case XftClipTypeNone:
947c76ae52dSmrg	break;
948c76ae52dSmrg    }
949c76ae52dSmrg
950c76ae52dSmrg    /*
951c76ae52dSmrg     * Set the clip
952c76ae52dSmrg     */
953c76ae52dSmrg    draw->clip_type = XftClipTypeRectangles;
954c76ae52dSmrg    draw->clip.rect = new;
955c76ae52dSmrg    /*
956c76ae52dSmrg     * Apply new clip to existing objects
957c76ae52dSmrg     */
958c76ae52dSmrg    if (draw->render.pict)
959c76ae52dSmrg    {
960c76ae52dSmrg	XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
961c76ae52dSmrg					 new->xOrigin,
962c76ae52dSmrg					 new->yOrigin,
963c76ae52dSmrg					 XftClipRects(new),
964c76ae52dSmrg					 new->n);
965c76ae52dSmrg    }
966c76ae52dSmrg    if (draw->core.gc)
967c76ae52dSmrg    {
968c76ae52dSmrg	XSetClipRectangles (draw->dpy, draw->core.gc,
969c76ae52dSmrg			    new->xOrigin,
970c76ae52dSmrg			    new->yOrigin,
971c76ae52dSmrg			    XftClipRects (new),
972c76ae52dSmrg			    new->n,
973c76ae52dSmrg			    Unsorted);
974c76ae52dSmrg    }
975c76ae52dSmrg    return True;
976c76ae52dSmrg}
977c76ae52dSmrg
978c76ae52dSmrg_X_EXPORT void
979c76ae52dSmrgXftDrawSetSubwindowMode (XftDraw *draw, int mode)
980c76ae52dSmrg{
981c76ae52dSmrg    if (mode == draw->subwindow_mode)
982c76ae52dSmrg	return;
983c76ae52dSmrg    draw->subwindow_mode = mode;
984c76ae52dSmrg    if (draw->render.pict)
985c76ae52dSmrg    {
986c76ae52dSmrg	XRenderPictureAttributes    pa;
987c76ae52dSmrg
988c76ae52dSmrg	pa.subwindow_mode = mode;
989c76ae52dSmrg	XRenderChangePicture (draw->dpy, draw->render.pict,
990c76ae52dSmrg			      CPSubwindowMode, &pa);
991c76ae52dSmrg    }
992c76ae52dSmrg    if (draw->core.gc)
993c76ae52dSmrg	XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
994c76ae52dSmrg}
995