Logo Search packages:      
Sourcecode: ia32-libs-gtk version File versions  Download package

xftdraw.c

/*
 * $Id: xftdraw.c,v 1.4 2005/07/03 07:00:57 daniels Exp $
 *
 * Copyright © 2000 Keith Packard
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Keith Packard not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Keith Packard makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include "xftint.h"

/*
 * Ok, this is a pain.  To share source pictures across multiple destinations,
 * the screen for each drawable must be discovered.
 */

static int
_XftDrawScreen (Display *dpy, Drawable drawable, Visual *visual)
{
    int               s;
    Window      root;
    int               x, y;
    unsigned int    width, height, borderWidth, depth;
    /* Special case the most common environment */
    if (ScreenCount (dpy) == 1)
      return 0;
    /*
     * If we've got a visual, look for the screen that points at it.
     * This requires no round trip.
     */
    if (visual)
    {
      for (s = 0; s < ScreenCount (dpy); s++)
      {
          XVisualInfo   template, *ret;
          int           nret;

          template.visualid = visual->visualid;
          template.screen = s;
          ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask,
                          &template, &nret);
          if (ret)
          {
            XFree (ret);
            return s;
          }
      }
    }
    /*
     * Otherwise, as the server for the drawable geometry and find
     * the screen from the root window.
     * This takes a round trip.
     */
    if (XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height,
                  &borderWidth, &depth))
    {
      for (s = 0; s < ScreenCount (dpy); s++)
      {
          if (RootWindow (dpy, s) == root)
            return s;
      }
    }
    /*
     * Make a guess -- it's probably wrong, but then the app probably
     * handed us a bogus drawable in this case
     */
    return 0;
}

unsigned int
XftDrawDepth (XftDraw *draw)
{
    if (!draw->depth)
    {
      Window                root;
      int             x, y;
      unsigned int          width, height, borderWidth, depth;
      if (XGetGeometry (draw->dpy, draw->drawable, 
                    &root, &x, &y, &width, &height,
                    &borderWidth, &depth))
          draw->depth = depth;
    }
    return draw->depth;
}

unsigned int
XftDrawBitsPerPixel (XftDraw  *draw)
{
    if (!draw->bits_per_pixel)
    {
      XPixmapFormatValues *formats;
      int             nformats;
      unsigned int          depth;
      
      if ((depth = XftDrawDepth (draw)) &&
          (formats = XListPixmapFormats (draw->dpy, &nformats)))
      {
          int     i;

          for (i = 0; i < nformats; i++)
          {
            if (formats[i].depth == depth)
            {
                draw->bits_per_pixel = formats[i].bits_per_pixel;
                break;
            }
          }
          XFree (formats);
      }
    }
    return draw->bits_per_pixel;
}

XftDraw *
XftDrawCreate (Display   *dpy,
             Drawable  drawable,
             Visual    *visual,
             Colormap  colormap)
{
    XftDraw *draw;

    draw = (XftDraw *) malloc (sizeof (XftDraw));
    if (!draw)
      return 0;
    
    draw->dpy = dpy;
    draw->drawable = drawable;
    draw->screen = _XftDrawScreen (dpy, drawable, visual);
    draw->depth = 0;          /* don't find out unless we need to know */
    draw->bits_per_pixel = 0; /* don't find out unless we need to know */
    draw->visual = visual;
    draw->colormap = colormap;
    draw->render.pict = 0;
    draw->core.gc = 0;
    draw->core.use_pixmap = 0;
    draw->clip_type = XftClipTypeNone;
    draw->subwindow_mode = ClipByChildren;
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
    return draw;
}

XftDraw *
XftDrawCreateBitmap (Display  *dpy,
                 Pixmap bitmap)
{
    XftDraw *draw;

    draw = (XftDraw *) malloc (sizeof (XftDraw));
    if (!draw)
      return 0;
    draw->dpy = dpy;
    draw->drawable = (Drawable) bitmap;
    draw->screen = _XftDrawScreen (dpy, bitmap, 0);
    draw->depth = 1;
    draw->bits_per_pixel = 1;
    draw->visual = 0;
    draw->colormap = 0;
    draw->render.pict = 0;
    draw->core.gc = 0;
    draw->core.use_pixmap = 0;
    draw->clip_type = XftClipTypeNone;
    draw->subwindow_mode = ClipByChildren;
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
    return draw;
}

XftDraw *
XftDrawCreateAlpha (Display *dpy,
                Pixmap  pixmap,
                int         depth)
{
    XftDraw *draw;

    draw = (XftDraw *) malloc (sizeof (XftDraw));
    if (!draw)
      return 0;
    draw->dpy = dpy;
    draw->drawable = (Drawable) pixmap;
    draw->screen = _XftDrawScreen (dpy, pixmap, 0);
    draw->depth = depth;
    draw->bits_per_pixel = 0; /* don't find out until we need it */
    draw->visual = 0;
    draw->colormap = 0;
    draw->render.pict = 0;
    draw->core.gc = 0;
    draw->core.use_pixmap = 0;
    draw->clip_type = XftClipTypeNone;
    draw->subwindow_mode = ClipByChildren;
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
    return draw;
}

static XRenderPictFormat *
_XftDrawFormat (XftDraw *draw)
{
    XftDisplayInfo  *info = _XftDisplayInfoGet (draw->dpy, True);

    if (!info->hasRender)
      return 0;

    if (draw->visual == 0)
    {
      XRenderPictFormat   pf;

      pf.type = PictTypeDirect;
      pf.depth = XftDrawDepth (draw);
      pf.direct.alpha = 0;
      pf.direct.alphaMask = (1 << pf.depth) - 1;
      return XRenderFindFormat (draw->dpy,
                          (PictFormatType|
                           PictFormatDepth|
                           PictFormatAlpha|
                           PictFormatAlphaMask),
                          &pf,
                          0);
    }
    else
      return XRenderFindVisualFormat (draw->dpy, draw->visual);
}

void
XftDrawChange (XftDraw  *draw,
             Drawable   drawable)
{
    draw->drawable = drawable;
    if (draw->render.pict)
    {
      XRenderFreePicture (draw->dpy, draw->render.pict);
      draw->render.pict = 0;
    }
    if (draw->core.gc)
    {
      XFreeGC (draw->dpy, draw->core.gc);
      draw->core.gc = 0;
    }
}

Display *
XftDrawDisplay (XftDraw *draw)
{
    return draw->dpy;
}

Drawable
XftDrawDrawable (XftDraw *draw)
{
    return draw->drawable;
}

Colormap
XftDrawColormap (XftDraw *draw)
{
    return draw->colormap;
}

Visual *
XftDrawVisual (XftDraw *draw)
{
    return draw->visual;
}

void
XftDrawDestroy (XftDraw *draw)
{
    if (draw->render.pict)
      XRenderFreePicture (draw->dpy, draw->render.pict);
    if (draw->core.gc)
      XFreeGC (draw->dpy, draw->core.gc);
    switch (draw->clip_type) {
    case XftClipTypeRegion:
      XDestroyRegion (draw->clip.region);
      break;
    case XftClipTypeRectangles:
      free (draw->clip.rect);
      break;
    case XftClipTypeNone:
      break;
    }
    XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw));
    free (draw);
}

Picture
XftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color)
{
    Display     *dpy = draw->dpy;
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
    int               i;
    XftColor          bitmapColor;

    if (!info)
      return 0;
    
    /*
     * Monochrome targets require special handling; the PictOp controls
     * the color, and the color must be opaque
     */
    if (!draw->visual && draw->depth == 1)
    {
      bitmapColor.color.alpha = 0xffff;
      bitmapColor.color.red   = 0xffff;
      bitmapColor.color.green = 0xffff;
      bitmapColor.color.blue  = 0xffff;
      color = &bitmapColor;
    }

    /*
     * See if there's one already available
     */
    for (i = 0; i < XFT_NUM_SOLID_COLOR; i++)
    {
      if (info->colors[i].pict && 
          info->colors[i].screen == draw->screen &&
          !memcmp ((void *) &color->color, 
                 (void *) &info->colors[i].color,
                 sizeof (XRenderColor)))
          return info->colors[i].pict;
    }
    /*
     * Pick one to replace at random
     */
    i = (unsigned int) rand () % XFT_NUM_SOLID_COLOR;
    /*
     * Recreate if it was for the wrong screen
     */
    if (info->colors[i].screen != draw->screen && info->colors[i].pict)
    {
      XRenderFreePicture (dpy, info->colors[i].pict);
      info->colors[i].pict = 0;
    }
    /*
     * Create picture if necessary
     */
    if (!info->colors[i].pict)
    {
      Pixmap                      pix;
        XRenderPictureAttributes    pa;
      
      pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1,
                       info->solidFormat->depth);
      pa.repeat = True;
      info->colors[i].pict = XRenderCreatePicture (draw->dpy,
                                         pix,
                                         info->solidFormat,
                                         CPRepeat, &pa);
      XFreePixmap (dpy, pix);
    }
    /*
     * Set to the new color
     */
    info->colors[i].color = color->color;
    info->colors[i].screen = draw->screen;
    XRenderFillRectangle (dpy, PictOpSrc,
                    info->colors[i].pict,
                    &color->color, 0, 0, 1, 1);
    return info->colors[i].pict;
}

static int
_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color)
{
    if (draw->visual || draw->depth != 1)
      return PictOpOver;
    if (color->color.alpha >= 0x8000)
      return PictOpOver;
    return PictOpOutReverse;
}

static FcBool
_XftDrawRenderPrepare (XftDraw      *draw)
{
    if (!draw->render.pict)
    {
      XRenderPictFormat     *format;
      XRenderPictureAttributes    pa;
      unsigned long               mask = 0;

      format = _XftDrawFormat (draw);
      if (!format)
          return FcFalse;
      
      if (draw->subwindow_mode == IncludeInferiors)
      {
          pa.subwindow_mode = IncludeInferiors;
          mask |= CPSubwindowMode;
      }
      draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable,
                                      format, mask, &pa);
      if (!draw->render.pict)
          return FcFalse;
      switch (draw->clip_type) {
      case XftClipTypeRegion:
          XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
                               draw->clip.region);
          break;
      case XftClipTypeRectangles:
          XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
                                   draw->clip.rect->xOrigin,
                                   draw->clip.rect->yOrigin,
                                   XftClipRects(draw->clip.rect),
                                   draw->clip.rect->n);
          break;
      case XftClipTypeNone:
          break;
      }
    }
    return FcTrue;
}

static FcBool
_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color)
{
    if (!draw->core.gc)
    {
      XGCValues   gcv;
      unsigned long     mask = 0;
      if (draw->subwindow_mode == IncludeInferiors)
      {
          gcv.subwindow_mode = IncludeInferiors;
          mask |= GCSubwindowMode;
      }
      draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv);
      if (!draw->core.gc)
          return FcFalse;
      switch (draw->clip_type) {
      case XftClipTypeRegion:
          XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
          break;
      case XftClipTypeRectangles:
          XSetClipRectangles (draw->dpy, draw->core.gc,
                        draw->clip.rect->xOrigin,
                        draw->clip.rect->yOrigin,
                        XftClipRects (draw->clip.rect),
                        draw->clip.rect->n,
                        Unsorted);
          break;
      case XftClipTypeNone:
          break;
      }
    }
    XSetForeground (draw->dpy, draw->core.gc, color->pixel);
    return FcTrue;
}
                  
Picture
XftDrawPicture (XftDraw *draw)
{
    if (!_XftDrawRenderPrepare (draw))
      return 0;
    return draw->render.pict;
}

#define NUM_LOCAL   1024

void
XftDrawGlyphs (XftDraw        *draw,
             _Xconst XftColor *color,
             XftFont          *pub,
             int        x,
             int        y,
             _Xconst FT_UInt  *glyphs,
             int        nglyphs)
{
    XftFontInt    *font = (XftFontInt *) pub;

    if (font->format)
    {
      Picture         src;
      
      if (_XftDrawRenderPrepare (draw) &&
          (src = XftDrawSrcPicture (draw, color)))
          XftGlyphRender (draw->dpy, _XftDrawOp (draw, color),
                       src, pub, draw->render.pict,
                       0, 0, x, y, glyphs, nglyphs);
    }
    else
    {
      if (_XftDrawCorePrepare (draw, color))
          XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs);
    }
}

void
XftDrawString8 (XftDraw           *draw,
            _Xconst XftColor    *color,
            XftFont               *pub,
            int             x, 
            int             y,
            _Xconst FcChar8       *string,
            int             len)
{
    FT_UInt     *glyphs, glyphs_local[NUM_LOCAL];
    int               i;

    if (XftDebug () & XFT_DBG_DRAW)
      printf ("DrawString \"%*.*s\"\n", len, len, string);
    
    if (len <= NUM_LOCAL)
      glyphs = glyphs_local;
    else
    {
      glyphs = malloc (len * sizeof (FT_UInt));
      if (!glyphs)
          return;
    }
    for (i = 0; i < len; i++)
      glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawString16 (XftDraw          *draw,
             _Xconst XftColor   *color,
             XftFont        *pub,
             int            x,
             int            y,
             _Xconst FcChar16   *string,
             int            len)
{
    FT_UInt     *glyphs, glyphs_local[NUM_LOCAL];
    int               i;

    if (len <= NUM_LOCAL)
      glyphs = glyphs_local;
    else
    {
      glyphs = malloc (len * sizeof (FT_UInt));
      if (!glyphs)
          return;
    }
    for (i = 0; i < len; i++)
      glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
    
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawString32 (XftDraw          *draw,
             _Xconst XftColor   *color,
             XftFont        *pub,
             int            x,
             int            y,
             _Xconst FcChar32   *string,
             int            len)
{
    FT_UInt     *glyphs, glyphs_local[NUM_LOCAL];
    int               i;

    if (len <= NUM_LOCAL)
      glyphs = glyphs_local;
    else
    {
      glyphs = malloc (len * sizeof (FT_UInt));
      if (!glyphs)
          return;
    }
    for (i = 0; i < len; i++)
      glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
    
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawStringUtf8 (XftDraw        *draw,
               _Xconst XftColor *color,
               XftFont      *pub,
               int                x, 
               int                y,
               _Xconst FcChar8  *string,
               int                len)
{
    FT_UInt     *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
    FcChar32          ucs4;
    int               i;
    int               l;
    int               size;

    i = 0;
    glyphs = glyphs_local;
    size = NUM_LOCAL;
    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
    {
      if (i == size)
      {
          glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
          if (!glyphs_new)
          {
            if (glyphs != glyphs_local)
                free (glyphs);
            return;
          }
          memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
          size *= 2;
          if (glyphs != glyphs_local)
            free (glyphs);
          glyphs = glyphs_new;
      }
      glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
      string += l;
      len -= l;
    }
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawStringUtf16 (XftDraw         *draw,
                _Xconst XftColor    *color,
                XftFont       *pub,
                int                 x,
                int                 y,
                _Xconst FcChar8     *string,
                FcEndian            endian,
                int                 len)
{
    FT_UInt     *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
    FcChar32          ucs4;
    int               i;
    int               l;
    int               size;

    i = 0;
    glyphs = glyphs_local;
    size = NUM_LOCAL;
    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
    {
      if (i == size)
      {
          glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
          if (!glyphs_new)
          {
            if (glyphs != glyphs_local)
                free (glyphs);
            return;
          }
          memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
          size *= 2;
          if (glyphs != glyphs_local)
            free (glyphs);
          glyphs = glyphs_new;
      }
      glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
      string += l;
      len -= l;
    }
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawGlyphSpec (XftDraw           *draw,
              _Xconst XftColor      *color,
              XftFont         *pub,
              _Xconst XftGlyphSpec  *glyphs,
              int             len)
{
    XftFontInt    *font = (XftFontInt *) pub;

    if (font->format)
    {
      Picture     src;

      if (_XftDrawRenderPrepare (draw) &&
          (src = XftDrawSrcPicture (draw, color)))
      {
          XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color),
                        src, pub, draw->render.pict,
                        0, 0, glyphs, len);
      }
    }
    else
    {
      if (_XftDrawCorePrepare (draw, color))
          XftGlyphSpecCore (draw, color, pub, glyphs, len);
    }
}

void
XftDrawGlyphFontSpec (XftDraw             *draw,
                  _Xconst XftColor        *color,
                  _Xconst XftGlyphFontSpec      *glyphs,
                  int               len)
{
    int           i;
    int           start;

    i = 0;
    while (i < len)
    {
      start = i;
      if (((XftFontInt *) glyphs[i].font)->format)
      {
          Picture src;
          while (i < len && ((XftFontInt *) glyphs[i].font)->format)
            i++;
          if (_XftDrawRenderPrepare (draw) &&
            (src = XftDrawSrcPicture (draw, color)))
          {
            XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color),
                              src, draw->render.pict,
                              0, 0, glyphs + start , i - start);
          }
      }
      else
      {
          while (i < len && !((XftFontInt *) glyphs[i].font)->format)
            i++;
          if (_XftDrawCorePrepare (draw, color))
            XftGlyphFontSpecCore (draw, color, glyphs + start, i - start);
      }
    }
}

void
XftDrawCharSpec (XftDraw            *draw,
             _Xconst XftColor *color,
             XftFont          *pub,
             _Xconst XftCharSpec    *chars,
             int              len)
{
    XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
    int               i;

    if (len <= NUM_LOCAL)
      glyphs = glyphs_local;
    else
    {
      glyphs = malloc (len * sizeof (XftGlyphSpec));
      if (!glyphs)
          return;
    }
    for (i = 0; i < len; i++)
    {
      glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4);
      glyphs[i].x = chars[i].x;
      glyphs[i].y = chars[i].y;
    }

    XftDrawGlyphSpec (draw, color, pub, glyphs, len);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawCharFontSpec (XftDraw              *draw,
                 _Xconst XftColor         *color,
                 _Xconst XftCharFontSpec  *chars,
                 int                len)
{
    XftGlyphFontSpec    *glyphs, glyphs_local[NUM_LOCAL];
    int                 i;

    if (len <= NUM_LOCAL)
      glyphs = glyphs_local;
    else
    {
      glyphs = malloc (len * sizeof (XftGlyphFontSpec));
      if (!glyphs)
          return;
    }
    for (i = 0; i < len; i++)
    {
      glyphs[i].font = chars[i].font;
      glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4);
      glyphs[i].x = chars[i].x;
      glyphs[i].y = chars[i].y;
    }

    XftDrawGlyphFontSpec (draw, color, glyphs, len);
    if (glyphs != glyphs_local)
      free (glyphs);
}

void
XftDrawRect (XftDraw          *draw,
           _Xconst XftColor   *color,
           int          x, 
           int          y,
           unsigned int width,
           unsigned int height)
{
    if (_XftDrawRenderPrepare (draw))
    {
      XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict,
                        &color->color, x, y, width, height);
    }
    else if (_XftDrawCorePrepare (draw, color))
    {
      XftRectCore (draw, color, x, y, width, height);
    }
}

Bool
XftDrawSetClip (XftDraw *draw,
            Region      r)
{
    Region              n = 0;

    /*
     * Check for quick exits
     */
    if (!r && draw->clip_type == XftClipTypeNone)
      return True;
    
    if (r && 
      draw->clip_type == XftClipTypeRegion && 
      XEqualRegion (r, draw->clip.region))
    {
      return True;
    }

    /*
     * Duplicate the region so future changes can be short circuited
     */
    if (r)
    {
      n = XCreateRegion ();
      if (n)
      {
          if (!XUnionRegion (n, r, n))
          {
            XDestroyRegion (n);
            return False;
          }
      }
    }

    /*
     * Destroy existing clip
     */
    switch (draw->clip_type) {
    case XftClipTypeRegion:
      XDestroyRegion (draw->clip.region);
      break;
    case XftClipTypeRectangles:
      free (draw->clip.rect);
      break;
    case XftClipTypeNone:
      break;
    }
    
    /*
     * Set the clip
     */
    if (n)
    {
      draw->clip_type = XftClipTypeRegion;
      draw->clip.region = n;
    }
    else
    {
      draw->clip_type = XftClipTypeNone;
    }
    /*
     * Apply new clip to existing objects
     */
    if (draw->render.pict)
    {
      if (n)
          XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n);
      else
      {
          XRenderPictureAttributes  pa;
          pa.clip_mask = None;
          XRenderChangePicture (draw->dpy, draw->render.pict,
                          CPClipMask, &pa);
      }
    }
    if (draw->core.gc)
    {
      if (n)
          XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
      else
          XSetClipMask (draw->dpy, draw->core.gc, None);
    }
    return True;
}

Bool
XftDrawSetClipRectangles (XftDraw         *draw,
                    int             xOrigin,
                    int             yOrigin,
                    _Xconst XRectangle    *rects,
                    int             n)
{
    XftClipRect   *new = 0;

    /*
     * Check for quick exit
     */
    if (draw->clip_type == XftClipTypeRectangles &&
      draw->clip.rect->n == n &&
      (n == 0 || (draw->clip.rect->xOrigin == xOrigin &&
                draw->clip.rect->yOrigin == yOrigin)) &&
      !memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle)))
    {
      return True;
    }

    /*
     * Duplicate the region so future changes can be short circuited
     */
    new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle));
    if (!new)
      return False;

    new->n = n;
    new->xOrigin = xOrigin;
    new->yOrigin = yOrigin;
    memcpy (XftClipRects (new), rects, n * sizeof (XRectangle));

    /*
     * Destroy existing clip
     */
    switch (draw->clip_type) {
    case XftClipTypeRegion:
      XDestroyRegion (draw->clip.region);
      break;
    case XftClipTypeRectangles:
      free (draw->clip.rect);
      break;
    case XftClipTypeNone:
      break;
    }
    
    /*
     * Set the clip
     */
    draw->clip_type = XftClipTypeRectangles;
    draw->clip.rect = new;
    /*
     * Apply new clip to existing objects
     */
    if (draw->render.pict)
    {
      XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
                               new->xOrigin,
                               new->yOrigin,
                               XftClipRects(new),
                               new->n);
    }
    if (draw->core.gc)
    {
      XSetClipRectangles (draw->dpy, draw->core.gc,
                      new->xOrigin,
                      new->yOrigin,
                      XftClipRects (new),
                      new->n,
                      Unsorted);
    }
    return True;
}

void
XftDrawSetSubwindowMode (XftDraw *draw, int mode)
{
    if (mode == draw->subwindow_mode)
      return;
    draw->subwindow_mode = mode;
    if (draw->render.pict)
    {
      XRenderPictureAttributes    pa;

      pa.subwindow_mode = mode;
      XRenderChangePicture (draw->dpy, draw->render.pict, 
                        CPSubwindowMode, &pa);
    }
    if (draw->core.gc)
      XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
}

Generated by  Doxygen 1.6.0   Back to index