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