2 * Copyright © 2000 Keith Packard
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.
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.
26 XftRectCore (XftDraw *draw,
27 _Xconst XftColor *color,
33 if (color->color.alpha >= 0x8000)
35 XSetForeground (draw->dpy, draw->core.gc, color->pixel);
36 XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
42 * Use the core protocol to draw the glyphs
46 _XftSharpGlyphMono (XftDraw *draw,
51 unsigned char *srcLine = glyph->bitmap, *src;
52 unsigned char bits, bitsMask;
53 int width = glyph->metrics.width;
54 int stride = ((width + 31) & ~31) >> 3;
55 int height = glyph->metrics.height;
59 x -= glyph->metrics.x;
60 y -= glyph->metrics.y;
67 bitsMask = 0x80; /* FreeType is always MSB first */
81 bitsMask = bitsMask >> 1;
87 } while (bits & bitsMask);
88 XFillRectangle (draw->dpy, draw->drawable,
89 draw->core.gc, xspan, y, lenspan, 1);
101 bitsMask = bitsMask >> 1;
107 } while (!(bits & bitsMask));
115 * Draw solid color text from an anti-aliased bitmap. This is a
116 * fallback for cases where a particular drawable has no AA code
119 _XftSharpGlyphGray (XftDraw *draw,
124 unsigned char *srcLine = glyph->bitmap, *src, bits;
125 int width = glyph->metrics.width;
126 int stride = ((width + 3) & ~3);
127 int height = glyph->metrics.height;
131 x -= glyph->metrics.x;
132 y -= glyph->metrics.y;
152 } while (bits >= 0x80);
153 XFillRectangle (draw->dpy, draw->drawable,
154 draw->core.gc, xspan, y, lenspan, 1);
167 } while (bits < 0x80);
175 _XftSharpGlyphRgba (XftDraw *draw,
180 CARD32 *srcLine = glyph->bitmap, *src, bits;
181 int width = glyph->metrics.width;
182 int stride = ((width + 3) & ~3);
183 int height = glyph->metrics.height;
187 x -= glyph->metrics.x;
188 y -= glyph->metrics.y;
199 if (bits >= 0x80000000)
208 } while (bits >= 0x80000000);
209 XFillRectangle (draw->dpy, draw->drawable,
210 draw->core.gc, xspan, y, lenspan, 1);
223 } while (bits < 0x80000000);
230 typedef void (*XftSharpGlyph) (XftDraw *draw,
236 _XftSharpGlyphFind (XftDraw *draw, XftFont *public)
238 XftFontInt *font = (XftFontInt *) public;
240 if (!font->info.antialias)
241 return _XftSharpGlyphMono;
242 else switch (font->info.rgba) {
247 return _XftSharpGlyphRgba;
249 return _XftSharpGlyphGray;
254 * Draw glyphs to a target that supports anti-aliasing
258 * Primitives for converting between RGB values and TrueColor pixels
262 _XftExamineBitfield (unsigned long mask, int *shift, int *len)
267 while ((mask & 1) == 0)
273 while ((mask & 1) == 1)
283 _XftGetField (unsigned long l_pixel, int shift, int len)
285 CARD32 pixel = (CARD32) l_pixel;
287 pixel = pixel & (((1 << (len)) - 1) << shift);
288 pixel = pixel << (32 - (shift + len)) >> 24;
291 pixel |= (pixel >> len);
298 _XftPutField (CARD32 pixel, int shift, int len)
300 unsigned long l_pixel = (unsigned long) pixel;
302 shift = shift - (8 - len);
304 l_pixel &= (((1 << len) - 1) << (8 - len));
313 * This is used when doing XftCharFontSpec/XftGlyphFontSpec where
314 * some of the fonts are bitmaps and some are anti-aliased to handle
315 * the bitmap portions
318 _XftSmoothGlyphMono (XImage *image,
319 _Xconst XftGlyph *xftg,
322 _Xconst XftColor *color)
324 unsigned char *srcLine = xftg->bitmap, *src;
325 unsigned char bits, bitsMask;
326 int width = xftg->metrics.width;
327 int stride = ((width + 31) & ~31) >> 3;
328 int height = xftg->metrics.height;
336 _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
337 _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
338 _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
339 pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) |
340 _XftPutField (color->color.green >> 8, g_shift, g_len) |
341 _XftPutField (color->color.blue >> 8, b_shift, b_len));
342 x -= xftg->metrics.x;
343 y -= xftg->metrics.y;
350 bitsMask = 0x80; /* FreeType is always MSB first */
357 XPutPixel (image, xspan, y, pixel);
358 bitsMask = bitsMask >> 1;
371 * As simple anti-aliasing is likely to be common, there are three
372 * optimized versions for the usual true color pixel formats (888, 565, 555).
373 * Other formats are handled by the general case
376 #define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \
377 (((s) >> 5) & 0x07e0) | \
378 (((s) >> 8) & 0xf800))
380 #define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
381 ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
382 ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
384 #define cvt8888to0555(s) ((((s) >> 3) & 0x001f) | \
385 (((s) >> 6) & 0x03e0) | \
386 (((s) >> 7) & 0x7c00))
388 #define cvt0555to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
389 ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
390 ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
393 #define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
394 #define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b))
396 #define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i))
399 * There are two ways of handling alpha -- either as a single unified value or
400 * a separate value for each component, hence each macro must have two
401 * versions. The unified alpha version has a 'U' at the end of the name,
402 * the component version has a 'C'. Similarly, functions which deal with
403 * this difference will have two versions using the same convention.
406 #define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\
407 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
409 #define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\
410 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
412 #define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i))
414 #define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i))
416 #define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \
417 XftIntMult(XftGet8(x,i),ax,(v))),\
418 (CARD32) ((CARD8) ((t) | \
419 (0 - ((t) >> 8)))) << (i))
421 #define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \
422 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
426 fbOver24 (CARD32 x, CARD32 y)
432 m = XftOverU(x,y,0,a,t);
433 n = XftOverU(x,y,8,a,t);
434 o = XftOverU(x,y,16,a,t);
439 fbIn (CARD32 x, CARD8 y)
447 o = XftInU(x,16,a,t);
448 p = XftInU(x,24,a,t);
453 _XftSmoothGlyphGray8888 (XImage *image,
454 _Xconst XftGlyph *xftg,
457 _Xconst XftColor *color)
461 CARD32 *dstLine, *dst, d;
462 CARD8 *maskLine, *mask, m;
463 int dstStride, maskStride;
467 srca = color->color.alpha >> 8;
469 /* This handles only RGB and BGR */
470 g = (color->color.green & 0xff00);
471 if (image->red_mask == 0xff0000)
473 r = (color->color.red & 0xff00) << 8;
474 b = color->color.blue >> 8;
478 r = color->color.red >> 8;
479 b = (color->color.blue & 0xff00) << 8;
481 src = (srca << 24) | r | g | b;
483 width = xftg->metrics.width;
484 height = xftg->metrics.height;
486 x -= xftg->metrics.x;
487 y -= xftg->metrics.y;
489 dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2));
490 dstStride = image->bytes_per_line >> 2;
491 maskLine = (unsigned char *) xftg->bitmap;
492 maskStride = (width + 3) & ~3;
497 dstLine += dstStride;
499 maskLine += maskStride;
510 *dst = fbOver24 (src, *dst);
515 *dst = fbOver24 (d, *dst);
523 _XftSmoothGlyphGray565 (XImage *image,
524 _Xconst XftGlyph *xftg,
527 _Xconst XftColor *color)
532 CARD16 *dstLine, *dst;
533 CARD8 *maskLine, *mask, m;
534 int dstStride, maskStride;
538 srca = color->color.alpha >> 8;
540 /* This handles only RGB and BGR */
541 g = (color->color.green & 0xff00);
542 if (image->red_mask == 0xf800)
544 r = (color->color.red & 0xff00) << 8;
545 b = color->color.blue >> 8;
549 r = color->color.red >> 8;
550 b = (color->color.blue & 0xff00) << 8;
552 src = (srca << 24) | r | g | b;
554 width = xftg->metrics.width;
555 height = xftg->metrics.height;
557 x -= xftg->metrics.x;
558 y -= xftg->metrics.y;
560 dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
561 dstStride = image->bytes_per_line >> 1;
562 maskLine = (unsigned char *) xftg->bitmap;
563 maskStride = (width + 3) & ~3;
568 dstLine += dstStride;
570 maskLine += maskStride;
583 d = fbOver24 (src, cvt0565to8888(d));
585 *dst = cvt8888to0565(d);
590 d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
591 *dst = cvt8888to0565(d);
599 _XftSmoothGlyphGray555 (XImage *image,
600 _Xconst XftGlyph *xftg,
603 _Xconst XftColor *color)
608 CARD16 *dstLine, *dst;
609 CARD8 *maskLine, *mask, m;
610 int dstStride, maskStride;
614 srca = color->color.alpha >> 8;
616 /* This handles only RGB and BGR */
617 g = (color->color.green & 0xff00);
618 if (image->red_mask == 0xf800)
620 r = (color->color.red & 0xff00) << 8;
621 b = color->color.blue >> 8;
625 r = color->color.red >> 8;
626 b = (color->color.blue & 0xff00) << 8;
628 src = (srca << 24) | r | g | b;
630 width = xftg->metrics.width;
631 height = xftg->metrics.height;
633 x -= xftg->metrics.x;
634 y -= xftg->metrics.y;
636 dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
637 dstStride = image->bytes_per_line >> 1;
638 maskLine = (unsigned char *) xftg->bitmap;
639 maskStride = (width + 3) & ~3;
644 dstLine += dstStride;
646 maskLine += maskStride;
659 d = fbOver24 (src, cvt0555to8888(d));
661 *dst = cvt8888to0555(d);
666 d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
667 *dst = cvt8888to0555(d);
675 _XftSmoothGlyphGray (XImage *image,
676 _Xconst XftGlyph *xftg,
679 _Xconst XftColor *color)
685 CARD8 *maskLine, *mask, m;
692 srca = color->color.alpha >> 8;
694 (color->color.red & 0xff00) << 8 |
695 (color->color.green & 0xff00) |
696 (color->color.blue) >> 8);
697 x -= xftg->metrics.x;
698 y -= xftg->metrics.y;
699 width = xftg->metrics.width;
700 height = xftg->metrics.height;
702 maskLine = (unsigned char *) xftg->bitmap;
703 maskStride = (width + 3) & ~3;
705 _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
706 _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
707 _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
711 maskLine += maskStride;
724 pixel = XGetPixel (image, tx, y);
725 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
726 _XftGetField (pixel, g_shift, g_len) << 8 |
727 _XftGetField (pixel, b_shift, b_len));
728 d = fbOver24 (src, d);
730 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
731 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
732 _XftPutField ((d ) & 0xff, b_shift, b_len));
733 XPutPixel (image, tx, y, pixel);
737 pixel = XGetPixel (image, tx, y);
738 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
739 _XftGetField (pixel, g_shift, g_len) << 8 |
740 _XftGetField (pixel, b_shift, b_len));
741 d = fbOver24 (fbIn(src,m), d);
742 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
743 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
744 _XftPutField ((d ) & 0xff, b_shift, b_len));
745 XPutPixel (image, tx, y, pixel);
754 _XftSmoothGlyphRgba (XImage *image,
755 _Xconst XftGlyph *xftg,
758 _Xconst XftColor *color)
770 srca = color->color.alpha >> 8;
772 (color->color.red & 0xff00) << 8 |
773 (color->color.green & 0xff00) |
774 (color->color.blue) >> 8);
775 x -= xftg->metrics.x;
776 y -= xftg->metrics.y;
777 width = xftg->metrics.width;
778 height = xftg->metrics.height;
780 mask = (CARD32 *) xftg->bitmap;
782 _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
783 _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
784 _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
793 if (ma == 0xffffffff)
799 pixel = XGetPixel (image, tx, y);
800 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
801 _XftGetField (pixel, g_shift, g_len) << 8 |
802 _XftGetField (pixel, b_shift, b_len));
803 d = fbOver24 (src, d);
805 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
806 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
807 _XftPutField ((d ) & 0xff, b_shift, b_len));
808 XPutPixel (image, tx, y, pixel);
813 pixel = XGetPixel (image, tx, y);
814 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
815 _XftGetField (pixel, g_shift, g_len) << 8 |
816 _XftGetField (pixel, b_shift, b_len));
817 #define XftInOverC(src,srca,msk,dst,i,result) { \
818 CARD16 __a = XftGet8(msk,i); \
821 __t = XftIntMult (XftGet8(src,i), __a,__i); \
822 __ta = (CARD8) ~XftIntMult (srca, __a,__i); \
823 __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \
824 __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
825 result = __t << (i); \
827 XftInOverC(src,srca,ma,d,0,m);
828 XftInOverC(src,srca,ma,d,8,n);
829 XftInOverC(src,srca,ma,d,16,o);
831 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
832 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
833 _XftPutField ((d ) & 0xff, b_shift, b_len));
834 XPutPixel (image, tx, y, pixel);
843 _XftSmoothGlyphPossible (XftDraw *draw)
847 if (draw->visual->class != TrueColor)
852 typedef void (*XftSmoothGlyph) (XImage *image,
853 _Xconst XftGlyph *xftg,
856 _Xconst XftColor *color);
858 static XftSmoothGlyph
859 _XftSmoothGlyphFind (XftDraw *draw, XftFont *public)
861 XftFontInt *font = (XftFontInt *) public;
863 if (!font->info.antialias)
864 return _XftSmoothGlyphMono;
865 else switch (font->info.rgba) {
870 return _XftSmoothGlyphRgba;
872 switch (XftDrawBitsPerPixel (draw)) {
874 if ((draw->visual->red_mask == 0xff0000 &&
875 draw->visual->green_mask == 0x00ff00 &&
876 draw->visual->blue_mask == 0x0000ff) ||
877 (draw->visual->red_mask == 0x0000ff &&
878 draw->visual->green_mask == 0x00ff00 &&
879 draw->visual->blue_mask == 0xff0000))
881 return _XftSmoothGlyphGray8888;
885 if ((draw->visual->red_mask == 0xf800 &&
886 draw->visual->green_mask == 0x07e0 &&
887 draw->visual->blue_mask == 0x001f) ||
888 (draw->visual->red_mask == 0x001f &&
889 draw->visual->green_mask == 0x07e0 &&
890 draw->visual->blue_mask == 0xf800))
892 return _XftSmoothGlyphGray565;
894 if ((draw->visual->red_mask == 0x7c00 &&
895 draw->visual->green_mask == 0x03e0 &&
896 draw->visual->blue_mask == 0x001f) ||
897 (draw->visual->red_mask == 0x001f &&
898 draw->visual->green_mask == 0x03e0 &&
899 draw->visual->blue_mask == 0x7c00))
901 return _XftSmoothGlyphGray555;
907 return _XftSmoothGlyphGray;
912 _XftGlyphDefault (Display *dpy, XftFont *public)
914 XftFontInt *font = (XftFontInt *) public;
915 FT_UInt missing[XFT_NMISSING];
917 FcBool glyphs_loaded = FcFalse;
919 if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing))
920 glyphs_loaded = FcTrue;
922 XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing);
923 return font->glyphs[0];
926 static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event)
932 XftGlyphCore (XftDraw *draw,
933 _Xconst XftColor *color,
937 _Xconst FT_UInt *glyphs,
940 Display *dpy = draw->dpy;
941 XftFontInt *font = (XftFontInt *) public;
945 FT_UInt missing[XFT_NMISSING];
946 FcBool glyphs_loaded;
949 XErrorHandler prev_error;
952 * Load missing glyphs
957 glyphs_loaded = FcFalse;
959 if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing))
960 glyphs_loaded = FcTrue;
962 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
966 if ((font->info.antialias || color->color.alpha != 0xffff) &&
967 _XftSmoothGlyphPossible (draw))
973 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
975 XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
976 if (!gi.width || !gi.height)
981 * Try to get bits directly from the drawable; if that fails,
982 * use a temporary pixmap. When it does fail, assume it
983 * will probably fail for a while and keep using temporary
984 * pixmaps for a while to avoid double round trips.
986 if (draw->core.use_pixmap == 0)
988 prev_error = XSetErrorHandler (XftGetImageErrorHandler);
989 image = XGetImage (dpy, draw->drawable,
991 gi.width, gi.height, AllPlanes,
993 XSetErrorHandler (prev_error);
995 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
999 draw->core.use_pixmap--;
1002 if (!image && (depth = XftDrawDepth (draw)))
1008 pix = XCreatePixmap (dpy, draw->drawable,
1009 gi.width, gi.height, depth);
1010 gcv.graphics_exposures = False;
1011 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1012 XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
1013 gi.width, gi.height, 0, 0);
1015 image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
1017 XFreePixmap (dpy, pix);
1021 image->red_mask = draw->visual->red_mask;
1022 image->green_mask = draw->visual->green_mask;
1023 image->blue_mask = draw->visual->blue_mask;
1024 if (image->byte_order != XftNativeByteOrder ())
1025 XftSwapImage (image);
1029 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1030 xftg = _XftGlyphDefault (dpy, public);
1033 (*smooth) (image, xftg, x - ox, y - oy, color);
1034 x += xftg->metrics.xOff;
1035 y += xftg->metrics.yOff;
1038 if (image->byte_order != XftNativeByteOrder ())
1039 XftSwapImage (image);
1040 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
1041 gi.width, gi.height);
1042 XDestroyImage (image);
1046 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
1050 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1051 xftg = _XftGlyphDefault (dpy, public);
1054 (*sharp) (draw, xftg, x, y);
1055 x += xftg->metrics.xOff;
1056 y += xftg->metrics.yOff;
1062 _XftFontManageMemory (dpy, public);
1065 #define NUM_LOCAL 1024
1068 XftGlyphSpecCore (XftDraw *draw,
1069 _Xconst XftColor *color,
1071 _Xconst XftGlyphSpec *glyphs,
1074 Display *dpy = draw->dpy;
1075 XftFontInt *font = (XftFontInt *) public;
1077 FT_UInt missing[XFT_NMISSING];
1078 FcBool glyphs_loaded;
1081 XErrorHandler prev_error;
1085 * Load missing glyphs
1087 glyphs_loaded = FcFalse;
1088 x1 = y1 = x2 = y2 = 0;
1089 for (i = 0; i < nglyphs; i++)
1092 int g_x1, g_x2, g_y1, g_y2;
1095 if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
1096 glyphs_loaded = FcTrue;
1098 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
1100 XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
1101 g_x1 = glyphs[i].x - gi.x;
1102 g_y1 = glyphs[i].y - gi.y;
1103 g_x2 = g_x1 + gi.width;
1104 g_y2 = g_y1 + gi.height;
1125 if (x1 == x2 || y1 == y2)
1128 if ((font->info.antialias || color->color.alpha != 0xffff) &&
1129 _XftSmoothGlyphPossible (draw))
1133 int width = x2 - x1, height = y2 - y1;
1134 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
1137 * Try to get bits directly from the drawable; if that fails,
1138 * use a temporary pixmap. When it does fail, assume it
1139 * will probably fail for a while and keep using temporary
1140 * pixmaps for a while to avoid double round trips.
1142 if (draw->core.use_pixmap == 0)
1144 prev_error = XSetErrorHandler (XftGetImageErrorHandler);
1145 image = XGetImage (dpy, draw->drawable,
1147 width, height, AllPlanes,
1149 XSetErrorHandler (prev_error);
1151 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
1155 draw->core.use_pixmap--;
1158 if (!image && (depth = XftDrawDepth (draw)))
1164 pix = XCreatePixmap (dpy, draw->drawable,
1165 width, height, depth);
1166 gcv.graphics_exposures = False;
1167 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1168 XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
1169 width, height, 0, 0);
1171 image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
1173 XFreePixmap (dpy, pix);
1177 image->red_mask = draw->visual->red_mask;
1178 image->green_mask = draw->visual->green_mask;
1179 image->blue_mask = draw->visual->blue_mask;
1180 if (image->byte_order != XftNativeByteOrder ())
1181 XftSwapImage (image);
1182 for (i = 0; i < nglyphs; i++)
1184 FT_UInt glyph = glyphs[i].glyph;
1185 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1186 xftg = _XftGlyphDefault (dpy, public);
1189 (*smooth) (image, xftg, glyphs[i].x - x1,
1190 glyphs[i].y - y1, color);
1193 if (image->byte_order != XftNativeByteOrder ())
1194 XftSwapImage (image);
1195 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
1197 XDestroyImage (image);
1201 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
1202 for (i = 0; i < nglyphs; i++)
1204 FT_UInt glyph = glyphs[i].glyph;
1205 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1206 xftg = _XftGlyphDefault (dpy, public);
1208 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
1213 _XftFontManageMemory (dpy, public);
1217 XftGlyphFontSpecCore (XftDraw *draw,
1218 _Xconst XftColor *color,
1219 _Xconst XftGlyphFontSpec *glyphs,
1222 Display *dpy = draw->dpy;
1224 FT_UInt missing[XFT_NMISSING];
1225 FcBool glyphs_loaded;
1228 XErrorHandler prev_error;
1232 * Load missing glyphs
1234 glyphs_loaded = FcFalse;
1235 x1 = y1 = x2 = y2 = 0;
1236 for (i = 0; i < nglyphs; i++)
1238 XftFont *public = glyphs[i].font;
1240 int g_x1, g_x2, g_y1, g_y2;
1243 if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
1244 glyphs_loaded = FcTrue;
1246 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
1248 XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
1249 g_x1 = glyphs[i].x - gi.x;
1250 g_y1 = glyphs[i].y - gi.y;
1251 g_x2 = g_x1 + gi.width;
1252 g_y2 = g_y1 + gi.height;
1273 if (x1 == x2 || y1 == y2)
1276 for (i = 0; i < nglyphs; i++)
1277 if (((XftFontInt *) glyphs[i].font)->info.antialias)
1280 if ((i != nglyphs || color->color.alpha != 0xffff) &&
1281 _XftSmoothGlyphPossible (draw))
1285 int width = x2 - x1, height = y2 - y1;
1288 * Try to get bits directly from the drawable; if that fails,
1289 * use a temporary pixmap. When it does fail, assume it
1290 * will probably fail for a while and keep using temporary
1291 * pixmaps for a while to avoid double round trips.
1293 if (draw->core.use_pixmap == 0)
1295 prev_error = XSetErrorHandler (XftGetImageErrorHandler);
1296 image = XGetImage (dpy, draw->drawable,
1298 width, height, AllPlanes,
1300 XSetErrorHandler (prev_error);
1302 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
1306 draw->core.use_pixmap--;
1309 if (!image && (depth = XftDrawDepth (draw)))
1315 pix = XCreatePixmap (dpy, draw->drawable,
1316 width, height, depth);
1317 gcv.graphics_exposures = False;
1318 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1319 XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
1320 width, height, 0, 0);
1322 image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
1324 XFreePixmap (dpy, pix);
1328 image->red_mask = draw->visual->red_mask;
1329 image->green_mask = draw->visual->green_mask;
1330 image->blue_mask = draw->visual->blue_mask;
1331 if (image->byte_order != XftNativeByteOrder ())
1332 XftSwapImage (image);
1333 for (i = 0; i < nglyphs; i++)
1335 XftFont *public = glyphs[i].font;
1336 XftFontInt *font = (XftFontInt *) public;
1337 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
1338 FT_UInt glyph = glyphs[i].glyph;
1340 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1341 xftg = _XftGlyphDefault (dpy, public);
1344 (*smooth) (image, xftg, glyphs[i].x - x1,
1345 glyphs[i].y - y1, color);
1348 if (image->byte_order != XftNativeByteOrder ())
1349 XftSwapImage (image);
1350 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
1352 XDestroyImage (image);
1356 for (i = 0; i < nglyphs; i++)
1358 XftFont *public = glyphs[i].font;
1359 XftFontInt *font = (XftFontInt *) public;
1360 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
1361 FT_UInt glyph = glyphs[i].glyph;
1363 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1364 xftg = _XftGlyphDefault (dpy, public);
1366 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
1371 for (i = 0; i < nglyphs; i++)
1372 _XftFontManageMemory (dpy, glyphs[i].font);