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