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