~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/Xft/xftdraw.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $XFree86: xc/lib/Xft/xftdraw.c,v 1.25 2002/10/11 17:53:02 keithp Exp $
 
3
 *
 
4
 * Copyright � 2000 Keith Packard, member of The XFree86 Project, Inc.
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include "xftint.h"
 
29
#include <X11/Xlib.h>
 
30
#include <X11/Xutil.h>
 
31
 
 
32
/*
 
33
 * Ok, this is a pain.  To share source pictures across multiple destinations,
 
34
 * the screen for each drawable must be discovered.
 
35
 */
 
36
 
 
37
static int
 
38
_XftDrawScreen (Display *dpy, Drawable drawable, Visual *visual)
 
39
{
 
40
    int             s;
 
41
    Window          root;
 
42
    int             x, y;
 
43
    unsigned int    width, height, borderWidth, depth;
 
44
    /* Special case the most common environment */
 
45
    if (ScreenCount (dpy) == 1)
 
46
        return 0;
 
47
    /*
 
48
     * If we've got a visual, look for the screen that points at it.
 
49
     * This requires no round trip.
 
50
     */
 
51
    if (visual)
 
52
    {
 
53
        for (s = 0; s < ScreenCount (dpy); s++)
 
54
        {
 
55
            XVisualInfo template, *ret;
 
56
            int         nret;
 
57
 
 
58
            template.visualid = visual->visualid;
 
59
            template.screen = s;
 
60
            ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask,
 
61
                                  &template, &nret);
 
62
            if (ret)
 
63
            {
 
64
                XFree (ret);
 
65
                return s;
 
66
            }
 
67
        }
 
68
    }
 
69
    /*
 
70
     * Otherwise, as the server for the drawable geometry and find
 
71
     * the screen from the root window.
 
72
     * This takes a round trip.
 
73
     */
 
74
    if (XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height,
 
75
                      &borderWidth, &depth))
 
76
    {
 
77
        for (s = 0; s < ScreenCount (dpy); s++)
 
78
        {
 
79
            if (RootWindow (dpy, s) == root)
 
80
                return s;
 
81
        }
 
82
    }
 
83
    /*
 
84
     * Make a guess -- it's probably wrong, but then the app probably
 
85
     * handed us a bogus drawable in this case
 
86
     */
 
87
    return 0;
 
88
}
 
89
 
 
90
unsigned int
 
91
XftDrawDepth (XftDraw *draw)
 
92
{
 
93
    if (!draw->depth)
 
94
    {
 
95
        Window              root;
 
96
        int                 x, y;
 
97
        unsigned int        width, height, borderWidth, depth;
 
98
        if (XGetGeometry (draw->dpy, draw->drawable, 
 
99
                          &root, &x, &y, &width, &height,
 
100
                          &borderWidth, &depth))
 
101
            draw->depth = depth;
 
102
    }
 
103
    return draw->depth;
 
104
}
 
105
 
 
106
unsigned int
 
107
XftDrawBitsPerPixel (XftDraw    *draw)
 
108
{
 
109
    if (!draw->bits_per_pixel)
 
110
    {
 
111
        XPixmapFormatValues *formats;
 
112
        int                 nformats;
 
113
        unsigned int        depth;
 
114
        
 
115
        if ((depth = XftDrawDepth (draw)) &&
 
116
            (formats = XListPixmapFormats (draw->dpy, &nformats)))
 
117
        {
 
118
            int i;
 
119
 
 
120
            for (i = 0; i < nformats; i++)
 
121
            {
 
122
                if (formats[i].depth == depth)
 
123
                {
 
124
                    draw->bits_per_pixel = formats[i].bits_per_pixel;
 
125
                    break;
 
126
                }
 
127
            }
 
128
            XFree (formats);
 
129
        }
 
130
    }
 
131
    return draw->bits_per_pixel;
 
132
}
 
133
 
 
134
XftDraw *
 
135
XftDrawCreate (Display   *dpy,
 
136
               Drawable  drawable,
 
137
               Visual    *visual,
 
138
               Colormap  colormap)
 
139
{
 
140
    XftDraw     *draw;
 
141
 
 
142
    draw = (XftDraw *) malloc (sizeof (XftDraw));
 
143
    if (!draw)
 
144
        return 0;
 
145
    
 
146
    draw->dpy = dpy;
 
147
    draw->drawable = drawable;
 
148
    draw->screen = _XftDrawScreen (dpy, drawable, visual);
 
149
    draw->depth = 0;            /* don't find out unless we need to know */
 
150
    draw->bits_per_pixel = 0;   /* don't find out unless we need to know */
 
151
    draw->visual = visual;
 
152
    draw->colormap = colormap;
 
153
    draw->render.pict = 0;
 
154
    draw->core.gc = 0;
 
155
    draw->core.use_pixmap = 0;
 
156
    draw->clip_type = XftClipTypeNone;
 
157
    draw->subwindow_mode = ClipByChildren;
 
158
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
 
159
    return draw;
 
160
}
 
161
 
 
162
XftDraw *
 
163
XftDrawCreateBitmap (Display    *dpy,
 
164
                     Pixmap     bitmap)
 
165
{
 
166
    XftDraw     *draw;
 
167
 
 
168
    draw = (XftDraw *) malloc (sizeof (XftDraw));
 
169
    if (!draw)
 
170
        return 0;
 
171
    draw->dpy = dpy;
 
172
    draw->drawable = (Drawable) bitmap;
 
173
    draw->screen = _XftDrawScreen (dpy, bitmap, 0);
 
174
    draw->depth = 1;
 
175
    draw->bits_per_pixel = 1;
 
176
    draw->visual = 0;
 
177
    draw->colormap = 0;
 
178
    draw->render.pict = 0;
 
179
    draw->core.gc = 0;
 
180
    draw->clip_type = XftClipTypeNone;
 
181
    draw->subwindow_mode = ClipByChildren;
 
182
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
 
183
    return draw;
 
184
}
 
185
 
 
186
XftDraw *
 
187
XftDrawCreateAlpha (Display *dpy,
 
188
                    Pixmap  pixmap,
 
189
                    int     depth)
 
190
{
 
191
    XftDraw     *draw;
 
192
 
 
193
    draw = (XftDraw *) malloc (sizeof (XftDraw));
 
194
    if (!draw)
 
195
        return 0;
 
196
    draw->dpy = dpy;
 
197
    draw->drawable = (Drawable) pixmap;
 
198
    draw->screen = _XftDrawScreen (dpy, pixmap, 0);
 
199
    draw->depth = depth;
 
200
    draw->bits_per_pixel = 0;   /* don't find out until we need it */
 
201
    draw->visual = 0;
 
202
    draw->colormap = 0;
 
203
    draw->render.pict = 0;
 
204
    draw->core.gc = 0;
 
205
    draw->clip_type = XftClipTypeNone;
 
206
    draw->subwindow_mode = ClipByChildren;
 
207
    XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
 
208
    return draw;
 
209
}
 
210
 
 
211
static XRenderPictFormat *
 
212
_XftDrawFormat (XftDraw *draw)
 
213
{
 
214
    XftDisplayInfo  *info = _XftDisplayInfoGet (draw->dpy, True);
 
215
 
 
216
    if (!info->hasRender)
 
217
        return 0;
 
218
 
 
219
    if (draw->visual == 0)
 
220
    {
 
221
        XRenderPictFormat   pf;
 
222
 
 
223
        pf.type = PictTypeDirect;
 
224
        pf.depth = XftDrawDepth (draw);
 
225
        pf.direct.alpha = 0;
 
226
        pf.direct.alphaMask = (1 << pf.depth) - 1;
 
227
        return XRenderFindFormat (draw->dpy,
 
228
                                  (PictFormatType|
 
229
                                   PictFormatDepth|
 
230
                                   PictFormatAlpha|
 
231
                                   PictFormatAlphaMask),
 
232
                                  &pf,
 
233
                                  0);
 
234
    }
 
235
    else
 
236
        return XRenderFindVisualFormat (draw->dpy, draw->visual);
 
237
}
 
238
 
 
239
void
 
240
XftDrawChange (XftDraw  *draw,
 
241
               Drawable drawable)
 
242
{
 
243
    draw->drawable = drawable;
 
244
    if (draw->render.pict)
 
245
    {
 
246
        XRenderFreePicture (draw->dpy, draw->render.pict);
 
247
        draw->render.pict = 0;
 
248
    }
 
249
    if (draw->core.gc)
 
250
    {
 
251
        XFreeGC (draw->dpy, draw->core.gc);
 
252
        draw->core.gc = 0;
 
253
    }
 
254
}
 
255
 
 
256
Display *
 
257
XftDrawDisplay (XftDraw *draw)
 
258
{
 
259
    return draw->dpy;
 
260
}
 
261
 
 
262
Drawable
 
263
XftDrawDrawable (XftDraw *draw)
 
264
{
 
265
    return draw->drawable;
 
266
}
 
267
 
 
268
Colormap
 
269
XftDrawColormap (XftDraw *draw)
 
270
{
 
271
    return draw->colormap;
 
272
}
 
273
 
 
274
Visual *
 
275
XftDrawVisual (XftDraw *draw)
 
276
{
 
277
    return draw->visual;
 
278
}
 
279
 
 
280
void
 
281
XftDrawDestroy (XftDraw *draw)
 
282
{
 
283
    if (draw->render.pict)
 
284
        XRenderFreePicture (draw->dpy, draw->render.pict);
 
285
    if (draw->core.gc)
 
286
        XFreeGC (draw->dpy, draw->core.gc);
 
287
    switch (draw->clip_type) {
 
288
    case XftClipTypeRegion:
 
289
        XDestroyRegion (draw->clip.region);
 
290
        break;
 
291
    case XftClipTypeRectangles:
 
292
        free (draw->clip.rect);
 
293
        break;
 
294
    case XftClipTypeNone:
 
295
        break;
 
296
    }
 
297
    XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw));
 
298
    free (draw);
 
299
}
 
300
 
 
301
Picture
 
302
XftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color)
 
303
{
 
304
    Display         *dpy = draw->dpy;
 
305
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
 
306
    int             i;
 
307
    XftColor        bitmapColor;
 
308
 
 
309
    if (!info)
 
310
        return 0;
 
311
    
 
312
    /*
 
313
     * Monochrome targets require special handling; the PictOp controls
 
314
     * the color, and the color must be opaque
 
315
     */
 
316
    if (!draw->visual && draw->depth == 1)
 
317
    {
 
318
        bitmapColor.color.alpha = 0xffff;
 
319
        bitmapColor.color.red   = 0xffff;
 
320
        bitmapColor.color.green = 0xffff;
 
321
        bitmapColor.color.blue  = 0xffff;
 
322
        color = &bitmapColor;
 
323
    }
 
324
 
 
325
    /*
 
326
     * See if there's one already available
 
327
     */
 
328
    for (i = 0; i < XFT_NUM_SOLID_COLOR; i++)
 
329
    {
 
330
        if (info->colors[i].pict && 
 
331
            info->colors[i].screen == draw->screen &&
 
332
            !memcmp ((void *) &color->color, 
 
333
                     (void *) &info->colors[i].color,
 
334
                     sizeof (XRenderColor)))
 
335
            return info->colors[i].pict;
 
336
    }
 
337
    /*
 
338
     * Pick one to replace at random
 
339
     */
 
340
    i = (unsigned int) rand () % XFT_NUM_SOLID_COLOR;
 
341
    /*
 
342
     * Recreate if it was for the wrong screen
 
343
     */
 
344
    if (info->colors[i].screen != draw->screen && info->colors[i].pict)
 
345
    {
 
346
        XRenderFreePicture (dpy, info->colors[i].pict);
 
347
        info->colors[i].pict = 0;
 
348
    }
 
349
    /*
 
350
     * Create picture if necessary
 
351
     */
 
352
    if (!info->colors[i].pict)
 
353
    {
 
354
        Pixmap                      pix;
 
355
        XRenderPictureAttributes    pa;
 
356
        
 
357
        pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1,
 
358
                             info->solidFormat->depth);
 
359
        pa.repeat = True;
 
360
        info->colors[i].pict = XRenderCreatePicture (draw->dpy,
 
361
                                                     pix,
 
362
                                                     info->solidFormat,
 
363
                                                     CPRepeat, &pa);
 
364
        XFreePixmap (dpy, pix);
 
365
    }
 
366
    /*
 
367
     * Set to the new color
 
368
     */
 
369
    info->colors[i].color = color->color;
 
370
    info->colors[i].screen = draw->screen;
 
371
    XRenderFillRectangle (dpy, PictOpSrc,
 
372
                          info->colors[i].pict,
 
373
                          &color->color, 0, 0, 1, 1);
 
374
    return info->colors[i].pict;
 
375
}
 
376
 
 
377
static int
 
378
_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color)
 
379
{
 
380
    if (draw->visual || draw->depth != 1)
 
381
        return PictOpOver;
 
382
    if (color->color.alpha >= 0x8000)
 
383
        return PictOpOver;
 
384
    return PictOpOutReverse;
 
385
}
 
386
 
 
387
static FcBool
 
388
_XftDrawRenderPrepare (XftDraw  *draw)
 
389
{
 
390
    if (!draw->render.pict)
 
391
    {
 
392
        XRenderPictFormat           *format;
 
393
        XRenderPictureAttributes    pa;
 
394
        unsigned long               mask = 0;
 
395
 
 
396
        format = _XftDrawFormat (draw);
 
397
        if (!format)
 
398
            return FcFalse;
 
399
        
 
400
        if (draw->subwindow_mode == IncludeInferiors)
 
401
        {
 
402
            pa.subwindow_mode = IncludeInferiors;
 
403
            mask |= CPSubwindowMode;
 
404
        }
 
405
        draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable,
 
406
                                                  format, mask, &pa);
 
407
        if (!draw->render.pict)
 
408
            return FcFalse;
 
409
        switch (draw->clip_type) {
 
410
        case XftClipTypeRegion:
 
411
            XRenderSetPictureClipRegion (draw->dpy, draw->render.pict,
 
412
                                         draw->clip.region);
 
413
            break;
 
414
        case XftClipTypeRectangles:
 
415
            XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
 
416
                                             draw->clip.rect->xOrigin,
 
417
                                             draw->clip.rect->yOrigin,
 
418
                                             XftClipRects(draw->clip.rect),
 
419
                                             draw->clip.rect->n);
 
420
            break;
 
421
        case XftClipTypeNone:
 
422
            break;
 
423
        }
 
424
    }
 
425
    return FcTrue;
 
426
}
 
427
 
 
428
static FcBool
 
429
_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color)
 
430
{
 
431
    if (!draw->core.gc)
 
432
    {
 
433
        XGCValues       gcv;
 
434
        unsigned long   mask = 0;
 
435
        if (draw->subwindow_mode == IncludeInferiors)
 
436
        {
 
437
            gcv.subwindow_mode = IncludeInferiors;
 
438
            mask |= GCSubwindowMode;
 
439
        }
 
440
        draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv);
 
441
        if (!draw->core.gc)
 
442
            return FcFalse;
 
443
        switch (draw->clip_type) {
 
444
        case XftClipTypeRegion:
 
445
            XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
 
446
            break;
 
447
        case XftClipTypeRectangles:
 
448
            XSetClipRectangles (draw->dpy, draw->core.gc,
 
449
                                draw->clip.rect->xOrigin,
 
450
                                draw->clip.rect->yOrigin,
 
451
                                XftClipRects (draw->clip.rect),
 
452
                                draw->clip.rect->n,
 
453
                                Unsorted);
 
454
            break;
 
455
        case XftClipTypeNone:
 
456
            break;
 
457
        }
 
458
    }
 
459
    XSetForeground (draw->dpy, draw->core.gc, color->pixel);
 
460
    return FcTrue;
 
461
}
 
462
                        
 
463
Picture
 
464
XftDrawPicture (XftDraw *draw)
 
465
{
 
466
    if (!_XftDrawRenderPrepare (draw))
 
467
        return 0;
 
468
    return draw->render.pict;
 
469
}
 
470
 
 
471
#define NUM_LOCAL   1024
 
472
 
 
473
void
 
474
XftDrawGlyphs (XftDraw          *draw,
 
475
               _Xconst XftColor *color,
 
476
               XftFont          *pub,
 
477
               int              x,
 
478
               int              y,
 
479
               _Xconst FT_UInt  *glyphs,
 
480
               int              nglyphs)
 
481
{
 
482
    XftFontInt  *font = (XftFontInt *) pub;
 
483
 
 
484
    if (font->format)
 
485
    {
 
486
        Picture     src;
 
487
        
 
488
        if (_XftDrawRenderPrepare (draw) &&
 
489
            (src = XftDrawSrcPicture (draw, color)))
 
490
            XftGlyphRender (draw->dpy, _XftDrawOp (draw, color),
 
491
                             src, pub, draw->render.pict,
 
492
                             0, 0, x, y, glyphs, nglyphs);
 
493
    }
 
494
    else
 
495
    {
 
496
        if (_XftDrawCorePrepare (draw, color))
 
497
            XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs);
 
498
    }
 
499
}
 
500
 
 
501
void
 
502
XftDrawString8 (XftDraw             *draw,
 
503
                _Xconst XftColor    *color,
 
504
                XftFont             *pub,
 
505
                int                 x, 
 
506
                int                 y,
 
507
                _Xconst FcChar8     *string,
 
508
                int                 len)
 
509
{
 
510
    FT_UInt         *glyphs, glyphs_local[NUM_LOCAL];
 
511
    int             i;
 
512
 
 
513
    if (XftDebug () & XFT_DBG_DRAW)
 
514
        printf ("DrawString \"%*.*s\"\n", len, len, string);
 
515
    
 
516
    if (len <= NUM_LOCAL)
 
517
        glyphs = glyphs_local;
 
518
    else
 
519
    {
 
520
        glyphs = malloc (len * sizeof (FT_UInt));
 
521
        if (!glyphs)
 
522
            return;
 
523
    }
 
524
    for (i = 0; i < len; i++)
 
525
        glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
 
526
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
 
527
    if (glyphs != glyphs_local)
 
528
        free (glyphs);
 
529
}
 
530
 
 
531
void
 
532
XftDrawString16 (XftDraw            *draw,
 
533
                 _Xconst XftColor   *color,
 
534
                 XftFont            *pub,
 
535
                 int                x,
 
536
                 int                y,
 
537
                 _Xconst FcChar16   *string,
 
538
                 int                len)
 
539
{
 
540
    FT_UInt         *glyphs, glyphs_local[NUM_LOCAL];
 
541
    int             i;
 
542
 
 
543
    if (len <= NUM_LOCAL)
 
544
        glyphs = glyphs_local;
 
545
    else
 
546
    {
 
547
        glyphs = malloc (len * sizeof (FT_UInt));
 
548
        if (!glyphs)
 
549
            return;
 
550
    }
 
551
    for (i = 0; i < len; i++)
 
552
        glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
 
553
    
 
554
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
 
555
    if (glyphs != glyphs_local)
 
556
        free (glyphs);
 
557
}
 
558
 
 
559
void
 
560
XftDrawString32 (XftDraw            *draw,
 
561
                 _Xconst XftColor   *color,
 
562
                 XftFont            *pub,
 
563
                 int                x,
 
564
                 int                y,
 
565
                 _Xconst FcChar32   *string,
 
566
                 int                len)
 
567
{
 
568
    FT_UInt         *glyphs, glyphs_local[NUM_LOCAL];
 
569
    int             i;
 
570
 
 
571
    if (len <= NUM_LOCAL)
 
572
        glyphs = glyphs_local;
 
573
    else
 
574
    {
 
575
        glyphs = malloc (len * sizeof (FT_UInt));
 
576
        if (!glyphs)
 
577
            return;
 
578
    }
 
579
    for (i = 0; i < len; i++)
 
580
        glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]);
 
581
    
 
582
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, len);
 
583
    if (glyphs != glyphs_local)
 
584
        free (glyphs);
 
585
}
 
586
 
 
587
void
 
588
XftDrawStringUtf8 (XftDraw          *draw,
 
589
                   _Xconst XftColor *color,
 
590
                   XftFont          *pub,
 
591
                   int              x, 
 
592
                   int              y,
 
593
                   _Xconst FcChar8  *string,
 
594
                   int              len)
 
595
{
 
596
    FT_UInt         *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
 
597
    FcChar32        ucs4;
 
598
    int             i;
 
599
    int             l;
 
600
    int             size;
 
601
 
 
602
    i = 0;
 
603
    glyphs = glyphs_local;
 
604
    size = NUM_LOCAL;
 
605
    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
 
606
    {
 
607
        if (i == size)
 
608
        {
 
609
            glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
 
610
            if (!glyphs_new)
 
611
            {
 
612
                if (glyphs != glyphs_local)
 
613
                    free (glyphs);
 
614
                return;
 
615
            }
 
616
            memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
 
617
            size *= 2;
 
618
            if (glyphs != glyphs_local)
 
619
                free (glyphs);
 
620
            glyphs = glyphs_new;
 
621
        }
 
622
        glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
 
623
        string += l;
 
624
        len -= l;
 
625
    }
 
626
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
 
627
    if (glyphs != glyphs_local)
 
628
        free (glyphs);
 
629
}
 
630
 
 
631
void
 
632
XftDrawStringUtf16 (XftDraw             *draw,
 
633
                    _Xconst XftColor    *color,
 
634
                    XftFont             *pub,
 
635
                    int                 x,
 
636
                    int                 y,
 
637
                    _Xconst FcChar8     *string,
 
638
                    FcEndian            endian,
 
639
                    int                 len)
 
640
{
 
641
    FT_UInt         *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
 
642
    FcChar32        ucs4;
 
643
    int             i;
 
644
    int             l;
 
645
    int             size;
 
646
 
 
647
    i = 0;
 
648
    glyphs = glyphs_local;
 
649
    size = NUM_LOCAL;
 
650
    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
 
651
    {
 
652
        if (i == size)
 
653
        {
 
654
            glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
 
655
            if (!glyphs_new)
 
656
            {
 
657
                if (glyphs != glyphs_local)
 
658
                    free (glyphs);
 
659
                return;
 
660
            }
 
661
            memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
 
662
            size *= 2;
 
663
            if (glyphs != glyphs_local)
 
664
                free (glyphs);
 
665
            glyphs = glyphs_new;
 
666
        }
 
667
        glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4);
 
668
        string += l;
 
669
        len -= l;
 
670
    }
 
671
    XftDrawGlyphs (draw, color, pub, x, y, glyphs, i);
 
672
    if (glyphs != glyphs_local)
 
673
        free (glyphs);
 
674
}
 
675
 
 
676
void
 
677
XftDrawGlyphSpec (XftDraw               *draw,
 
678
                  _Xconst XftColor      *color,
 
679
                  XftFont               *pub,
 
680
                  _Xconst XftGlyphSpec  *glyphs,
 
681
                  int                   len)
 
682
{
 
683
    XftFontInt  *font = (XftFontInt *) pub;
 
684
 
 
685
    if (font->format)
 
686
    {
 
687
        Picture src;
 
688
 
 
689
        if (_XftDrawRenderPrepare (draw) &&
 
690
            (src = XftDrawSrcPicture (draw, color)))
 
691
        {
 
692
            XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color),
 
693
                                src, pub, draw->render.pict,
 
694
                                0, 0, glyphs, len);
 
695
        }
 
696
    }
 
697
    else
 
698
    {
 
699
        if (_XftDrawCorePrepare (draw, color))
 
700
            XftGlyphSpecCore (draw, color, pub, glyphs, len);
 
701
    }
 
702
}
 
703
 
 
704
void
 
705
XftDrawGlyphFontSpec (XftDraw                   *draw,
 
706
                      _Xconst XftColor          *color,
 
707
                      _Xconst XftGlyphFontSpec  *glyphs,
 
708
                      int                       len)
 
709
{
 
710
    int         i;
 
711
    int         start;
 
712
 
 
713
    i = 0;
 
714
    while (i < len)
 
715
    {
 
716
        start = i;
 
717
        if (((XftFontInt *) glyphs[i].font)->format)
 
718
        {
 
719
            Picture     src;
 
720
            while (i < len && ((XftFontInt *) glyphs[i].font)->format)
 
721
                i++;
 
722
            if (_XftDrawRenderPrepare (draw) &&
 
723
                (src = XftDrawSrcPicture (draw, color)))
 
724
            {
 
725
                XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color),
 
726
                                        src, draw->render.pict,
 
727
                                        0, 0, glyphs, i - start);
 
728
            }
 
729
        }
 
730
        else
 
731
        {
 
732
            while (i < len && !((XftFontInt *) glyphs[i].font)->format)
 
733
                i++;
 
734
            if (_XftDrawCorePrepare (draw, color))
 
735
                XftGlyphFontSpecCore (draw, color, glyphs, len);
 
736
        }
 
737
    }
 
738
}
 
739
 
 
740
void
 
741
XftDrawCharSpec (XftDraw                *draw,
 
742
                 _Xconst XftColor       *color,
 
743
                 XftFont                *pub,
 
744
                 _Xconst XftCharSpec    *chars,
 
745
                 int                    len)
 
746
{
 
747
    XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
 
748
    int             i;
 
749
 
 
750
    if (len <= NUM_LOCAL)
 
751
        glyphs = glyphs_local;
 
752
    else
 
753
    {
 
754
        glyphs = malloc (len * sizeof (XftGlyphSpec));
 
755
        if (!glyphs)
 
756
            return;
 
757
    }
 
758
    for (i = 0; i < len; i++)
 
759
    {
 
760
        glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4);
 
761
        glyphs[i].x = chars[i].x;
 
762
        glyphs[i].y = chars[i].y;
 
763
    }
 
764
 
 
765
    XftDrawGlyphSpec (draw, color, pub, glyphs, len);
 
766
    if (glyphs != glyphs_local)
 
767
        free (glyphs);
 
768
}
 
769
 
 
770
void
 
771
XftDrawCharFontSpec (XftDraw                    *draw,
 
772
                     _Xconst XftColor           *color,
 
773
                     _Xconst XftCharFontSpec    *chars,
 
774
                     int                        len)
 
775
{
 
776
    XftGlyphFontSpec    *glyphs, glyphs_local[NUM_LOCAL];
 
777
    int                 i;
 
778
 
 
779
    if (len <= NUM_LOCAL)
 
780
        glyphs = glyphs_local;
 
781
    else
 
782
    {
 
783
        glyphs = malloc (len * sizeof (XftGlyphFontSpec));
 
784
        if (!glyphs)
 
785
            return;
 
786
    }
 
787
    for (i = 0; i < len; i++)
 
788
    {
 
789
        glyphs[i].font = chars[i].font;
 
790
        glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4);
 
791
        glyphs[i].x = chars[i].x;
 
792
        glyphs[i].y = chars[i].y;
 
793
    }
 
794
 
 
795
    XftDrawGlyphFontSpec (draw, color, glyphs, len);
 
796
    if (glyphs != glyphs_local)
 
797
        free (glyphs);
 
798
}
 
799
 
 
800
void
 
801
XftDrawRect (XftDraw            *draw,
 
802
             _Xconst XftColor   *color,
 
803
             int                x, 
 
804
             int                y,
 
805
             unsigned int       width,
 
806
             unsigned int       height)
 
807
{
 
808
    if (_XftDrawRenderPrepare (draw))
 
809
    {
 
810
        XRenderFillRectangle (draw->dpy, PictOpOver, draw->render.pict,
 
811
                              &color->color, x, y, width, height);
 
812
    }
 
813
    else if (_XftDrawCorePrepare (draw, color))
 
814
    {
 
815
        XftRectCore (draw, color, x, y, width, height);
 
816
    }
 
817
}
 
818
 
 
819
Bool
 
820
XftDrawSetClip (XftDraw *draw,
 
821
                Region  r)
 
822
{
 
823
    Region                      n = 0;
 
824
 
 
825
    /*
 
826
     * Check for quick exits
 
827
     */
 
828
    if (!r && draw->clip_type == XftClipTypeNone)
 
829
        return True;
 
830
    
 
831
    if (r && 
 
832
        draw->clip_type == XftClipTypeRegion && 
 
833
        XEqualRegion (r, draw->clip.region))
 
834
    {
 
835
        return True;
 
836
    }
 
837
 
 
838
    /*
 
839
     * Duplicate the region so future changes can be short circuited
 
840
     */
 
841
    if (r)
 
842
    {
 
843
        n = XCreateRegion ();
 
844
        if (n)
 
845
        {
 
846
            if (!XUnionRegion (n, r, n))
 
847
            {
 
848
                XDestroyRegion (n);
 
849
                return False;
 
850
            }
 
851
        }
 
852
    }
 
853
 
 
854
    /*
 
855
     * Destroy existing clip
 
856
     */
 
857
    switch (draw->clip_type) {
 
858
    case XftClipTypeRegion:
 
859
        XDestroyRegion (draw->clip.region);
 
860
        break;
 
861
    case XftClipTypeRectangles:
 
862
        free (draw->clip.rect);
 
863
        break;
 
864
    case XftClipTypeNone:
 
865
        break;
 
866
    }
 
867
    
 
868
    /*
 
869
     * Set the clip
 
870
     */
 
871
    if (n)
 
872
    {
 
873
        draw->clip_type = XftClipTypeRegion;
 
874
        draw->clip.region = n;
 
875
    }
 
876
    else
 
877
    {
 
878
        draw->clip_type = XftClipTypeNone;
 
879
    }
 
880
    /*
 
881
     * Apply new clip to existing objects
 
882
     */
 
883
    if (draw->render.pict)
 
884
    {
 
885
        if (n)
 
886
            XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n);
 
887
        else
 
888
        {
 
889
            XRenderPictureAttributes    pa;
 
890
            pa.clip_mask = None;
 
891
            XRenderChangePicture (draw->dpy, draw->render.pict,
 
892
                                  CPClipMask, &pa);
 
893
        }
 
894
    }
 
895
    if (draw->core.gc)
 
896
    {
 
897
        if (n)
 
898
            XSetRegion (draw->dpy, draw->core.gc, draw->clip.region);
 
899
        else
 
900
            XSetClipMask (draw->dpy, draw->core.gc, None);
 
901
    }
 
902
    return True;
 
903
}
 
904
 
 
905
Bool
 
906
XftDrawSetClipRectangles (XftDraw               *draw,
 
907
                          int                   xOrigin,
 
908
                          int                   yOrigin,
 
909
                          _Xconst XRectangle    *rects,
 
910
                          int                   n)
 
911
{
 
912
    XftClipRect *new = 0;
 
913
 
 
914
    /*
 
915
     * Check for quick exit
 
916
     */
 
917
    if (draw->clip_type == XftClipTypeRectangles && 
 
918
        !memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle)))
 
919
    {
 
920
        return True;
 
921
    }
 
922
 
 
923
    /*
 
924
     * Duplicate the region so future changes can be short circuited
 
925
     */
 
926
    new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle));
 
927
    if (!new)
 
928
        return False;
 
929
 
 
930
    new->n = n;
 
931
    new->xOrigin = xOrigin;
 
932
    new->yOrigin = yOrigin;
 
933
    memcpy (XftClipRects (new), rects, n * sizeof (XRectangle));
 
934
 
 
935
    /*
 
936
     * Destroy existing clip
 
937
     */
 
938
    switch (draw->clip_type) {
 
939
    case XftClipTypeRegion:
 
940
        XDestroyRegion (draw->clip.region);
 
941
        break;
 
942
    case XftClipTypeRectangles:
 
943
        free (draw->clip.rect);
 
944
        break;
 
945
    case XftClipTypeNone:
 
946
        break;
 
947
    }
 
948
    
 
949
    /*
 
950
     * Set the clip
 
951
     */
 
952
    draw->clip_type = XftClipTypeRectangles;
 
953
    draw->clip.rect = new;
 
954
    /*
 
955
     * Apply new clip to existing objects
 
956
     */
 
957
    if (draw->render.pict)
 
958
    {
 
959
        XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict,
 
960
                                         new->xOrigin,
 
961
                                         new->yOrigin,
 
962
                                         XftClipRects(new),
 
963
                                         new->n);
 
964
    }
 
965
    if (draw->core.gc)
 
966
    {
 
967
        XSetClipRectangles (draw->dpy, draw->core.gc,
 
968
                            new->xOrigin,
 
969
                            new->yOrigin,
 
970
                            XftClipRects (new),
 
971
                            new->n,
 
972
                            Unsorted);
 
973
    }
 
974
    return True;
 
975
}
 
976
 
 
977
void
 
978
XftDrawSetSubwindowMode (XftDraw *draw, int mode)
 
979
{
 
980
    if (mode == draw->subwindow_mode)
 
981
        return;
 
982
    draw->subwindow_mode = mode;
 
983
    if (draw->render.pict)
 
984
    {
 
985
        XRenderPictureAttributes    pa;
 
986
 
 
987
        pa.subwindow_mode = mode;
 
988
        XRenderChangePicture (draw->dpy, draw->render.pict, 
 
989
                              CPSubwindowMode, &pa);
 
990
    }
 
991
    if (draw->core.gc)
 
992
        XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
 
993
}