aboutsummaryrefslogtreecommitdiff
path: root/libXft/src
diff options
context:
space:
mode:
Diffstat (limited to 'libXft/src')
-rw-r--r--libXft/src/xftcore.c2756
-rw-r--r--libXft/src/xftdpy.c1104
-rw-r--r--libXft/src/xftdraw.c1988
3 files changed, 2929 insertions, 2919 deletions
diff --git a/libXft/src/xftcore.c b/libXft/src/xftcore.c
index 3f8710929..04fa47640 100644
--- a/libXft/src/xftcore.c
+++ b/libXft/src/xftcore.c
@@ -1,1373 +1,1383 @@
-/*
- * 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"
-
-_X_HIDDEN void
-XftRectCore (XftDraw *draw,
- _Xconst XftColor *color,
- int x,
- int y,
- unsigned int width,
- unsigned int height)
-{
- if (color->color.alpha >= 0x8000)
- {
- XSetForeground (draw->dpy, draw->core.gc, color->pixel);
- XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
- x, y, width, height);
- }
-}
-
-/*
- * Use the core protocol to draw the glyphs
- */
-
-static void
-_XftSharpGlyphMono (XftDraw *draw,
- XftGlyph *glyph,
- int x,
- int y)
-{
- unsigned char *srcLine = glyph->bitmap, *src;
- unsigned char bits, bitsMask;
- int width = glyph->metrics.width;
- int stride = ((width + 31) & ~31) >> 3;
- int height = glyph->metrics.height;
- int w;
- int xspan, lenspan;
-
- x -= glyph->metrics.x;
- y -= glyph->metrics.y;
- while (height--)
- {
- src = srcLine;
- srcLine += stride;
- w = width;
-
- bitsMask = 0x80; /* FreeType is always MSB first */
- bits = *src++;
-
- xspan = x;
- while (w)
- {
- if (bits & bitsMask)
- {
- lenspan = 0;
- do
- {
- lenspan++;
- if (lenspan == w)
- break;
- bitsMask = bitsMask >> 1;
- if (!bitsMask)
- {
- bits = *src++;
- bitsMask = 0x80;
- }
- } while (bits & bitsMask);
- XFillRectangle (draw->dpy, draw->drawable,
- draw->core.gc, xspan, y, lenspan, 1);
- xspan += lenspan;
- w -= lenspan;
- }
- else
- {
- do
- {
- w--;
- xspan++;
- if (!w)
- break;
- bitsMask = bitsMask >> 1;
- if (!bitsMask)
- {
- bits = *src++;
- bitsMask = 0x80;
- }
- } while (!(bits & bitsMask));
- }
- }
- y++;
- }
-}
-
-/*
- * Draw solid color text from an anti-aliased bitmap. This is a
- * fallback for cases where a particular drawable has no AA code
- */
-static void
-_XftSharpGlyphGray (XftDraw *draw,
- XftGlyph *glyph,
- int x,
- int y)
-{
- unsigned char *srcLine = glyph->bitmap, *src, bits;
- int width = glyph->metrics.width;
- int stride = ((width + 3) & ~3);
- int height = glyph->metrics.height;
- int w;
- int xspan, lenspan;
-
- x -= glyph->metrics.x;
- y -= glyph->metrics.y;
- while (height--)
- {
- src = srcLine;
- srcLine += stride;
- w = width;
-
- bits = *src++;
- xspan = x;
- while (w)
- {
- if (bits >= 0x80)
- {
- lenspan = 0;
- do
- {
- lenspan++;
- if (lenspan == w)
- break;
- bits = *src++;
- } while (bits >= 0x80);
- XFillRectangle (draw->dpy, draw->drawable,
- draw->core.gc, xspan, y, lenspan, 1);
- xspan += lenspan;
- w -= lenspan;
- }
- else
- {
- do
- {
- w--;
- xspan++;
- if (!w)
- break;
- bits = *src++;
- } while (bits < 0x80);
- }
- }
- y++;
- }
-}
-
-static void
-_XftSharpGlyphRgba (XftDraw *draw,
- XftGlyph *glyph,
- int x,
- int y)
-{
- CARD32 *srcLine = glyph->bitmap, *src, bits;
- int width = glyph->metrics.width;
- int stride = ((width + 3) & ~3);
- int height = glyph->metrics.height;
- int w;
- int xspan, lenspan;
-
- x -= glyph->metrics.x;
- y -= glyph->metrics.y;
- while (height--)
- {
- src = srcLine;
- srcLine += stride;
- w = width;
-
- bits = *src++;
- xspan = x;
- while (w)
- {
- if (bits >= 0x80000000)
- {
- lenspan = 0;
- do
- {
- lenspan++;
- if (lenspan == w)
- break;
- bits = *src++;
- } while (bits >= 0x80000000);
- XFillRectangle (draw->dpy, draw->drawable,
- draw->core.gc, xspan, y, lenspan, 1);
- xspan += lenspan;
- w -= lenspan;
- }
- else
- {
- do
- {
- w--;
- xspan++;
- if (!w)
- break;
- bits = *src++;
- } while (bits < 0x80000000);
- }
- }
- y++;
- }
-}
-
-typedef void (*XftSharpGlyph) (XftDraw *draw,
- XftGlyph *glyph,
- int x,
- int y);
-
-static XftSharpGlyph
-_XftSharpGlyphFind (XftDraw *draw, XftFont *public)
-{
- XftFontInt *font = (XftFontInt *) public;
-
- if (!font->info.antialias)
- return _XftSharpGlyphMono;
- else switch (font->info.rgba) {
- case FC_RGBA_RGB:
- case FC_RGBA_BGR:
- case FC_RGBA_VRGB:
- case FC_RGBA_VBGR:
- return _XftSharpGlyphRgba;
- default:
- return _XftSharpGlyphGray;
- }
-}
-
-/*
- * Draw glyphs to a target that supports anti-aliasing
- */
-
-/*
- * Primitives for converting between RGB values and TrueColor pixels
- */
-
-static void
-_XftExamineBitfield (unsigned long mask, int *shift, int *len)
-{
- int s, l;
-
- s = 0;
- while ((mask & 1) == 0)
- {
- mask >>= 1;
- s++;
- }
- l = 0;
- while ((mask & 1) == 1)
- {
- mask >>= 1;
- l++;
- }
- *shift = s;
- *len = l;
-}
-
-static CARD32
-_XftGetField (unsigned long l_pixel, int shift, int len)
-{
- CARD32 pixel = (CARD32) l_pixel;
-
- pixel = pixel & (((1 << (len)) - 1) << shift);
- pixel = pixel << (32 - (shift + len)) >> 24;
- while (len < 8)
- {
- pixel |= (pixel >> len);
- len <<= 1;
- }
- return pixel;
-}
-
-static unsigned long
-_XftPutField (CARD32 pixel, int shift, int len)
-{
- unsigned long l_pixel = (unsigned long) pixel;
-
- shift = shift - (8 - len);
- if (len <= 8)
- l_pixel &= (((1 << len) - 1) << (8 - len));
- if (shift < 0)
- l_pixel >>= -shift;
- else
- l_pixel <<= shift;
- return l_pixel;
-}
-
-/*
- * This is used when doing XftCharFontSpec/XftGlyphFontSpec where
- * some of the fonts are bitmaps and some are anti-aliased to handle
- * the bitmap portions
- */
-static void
-_XftSmoothGlyphMono (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- unsigned char *srcLine = xftg->bitmap, *src;
- unsigned char bits, bitsMask;
- int width = xftg->metrics.width;
- int stride = ((width + 31) & ~31) >> 3;
- int height = xftg->metrics.height;
- int w;
- int xspan;
- int r_shift, r_len;
- int g_shift, g_len;
- int b_shift, b_len;
- unsigned long pixel;
-
- _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
- _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
- _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
- pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) |
- _XftPutField (color->color.green >> 8, g_shift, g_len) |
- _XftPutField (color->color.blue >> 8, b_shift, b_len));
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
- while (height--)
- {
- src = srcLine;
- srcLine += stride;
- w = width;
-
- bitsMask = 0x80; /* FreeType is always MSB first */
- bits = *src++;
-
- xspan = x;
- while (w--)
- {
- if (bits & bitsMask)
- XPutPixel (image, xspan, y, pixel);
- bitsMask = bitsMask >> 1;
- if (!bitsMask)
- {
- bits = *src++;
- bitsMask = 0x80;
- }
- xspan++;
- }
- y++;
- }
-}
-
-/*
- * As simple anti-aliasing is likely to be common, there are three
- * optimized versions for the usual true color pixel formats (888, 565, 555).
- * Other formats are handled by the general case
- */
-
-#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \
- (((s) >> 5) & 0x07e0) | \
- (((s) >> 8) & 0xf800))
-
-#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
- ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
- ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
-
-#define cvt8888to0555(s) ((((s) >> 3) & 0x001f) | \
- (((s) >> 6) & 0x03e0) | \
- (((s) >> 7) & 0x7c00))
-
-#define cvt0555to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
- ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
- ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
-
-
-#define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
-#define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b))
-
-#define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i))
-
-/*
- * There are two ways of handling alpha -- either as a single unified value or
- * a separate value for each component, hence each macro must have two
- * versions. The unified alpha version has a 'U' at the end of the name,
- * the component version has a 'C'. Similarly, functions which deal with
- * this difference will have two versions using the same convention.
- */
-
-#define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\
- (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
-
-#define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\
- (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
-
-#define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i))
-
-#define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i))
-
-#define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \
- XftIntMult(XftGet8(x,i),ax,(v))),\
- (CARD32) ((CARD8) ((t) | \
- (0 - ((t) >> 8)))) << (i))
-
-#define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \
- (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
-
-
-static CARD32
-fbOver24 (CARD32 x, CARD32 y)
-{
- CARD16 a = ~x >> 24;
- CARD16 t;
- CARD32 m,n,o;
-
- m = XftOverU(x,y,0,a,t);
- n = XftOverU(x,y,8,a,t);
- o = XftOverU(x,y,16,a,t);
- return m|n|o;
-}
-
-static CARD32
-fbIn (CARD32 x, CARD8 y)
-{
- CARD16 a = y;
- CARD16 t;
- CARD32 m,n,o,p;
-
- m = XftInU(x,0,a,t);
- n = XftInU(x,8,a,t);
- o = XftInU(x,16,a,t);
- p = XftInU(x,24,a,t);
- return m|n|o|p;
-}
-
-static void
-_XftSmoothGlyphGray8888 (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- CARD32 src, srca;
- CARD32 r, g, b;
- CARD32 *dstLine, *dst, d;
- CARD8 *maskLine, *mask, m;
- int dstStride, maskStride;
- int width, height;
- int w;
-
- srca = color->color.alpha >> 8;
-
- /* This handles only RGB and BGR */
- g = (color->color.green & 0xff00);
- if (image->red_mask == 0xff0000)
- {
- r = (color->color.red & 0xff00) << 8;
- b = color->color.blue >> 8;
- }
- else
- {
- r = color->color.red >> 8;
- b = (color->color.blue & 0xff00) << 8;
- }
- src = (srca << 24) | r | g | b;
-
- width = xftg->metrics.width;
- height = xftg->metrics.height;
-
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
-
- dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2));
- dstStride = image->bytes_per_line >> 2;
- maskLine = (unsigned char *) xftg->bitmap;
- maskStride = (width + 3) & ~3;
-
- while (height--)
- {
- dst = dstLine;
- dstLine += dstStride;
- mask = maskLine;
- maskLine += maskStride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- *dst = src;
- else
- *dst = fbOver24 (src, *dst);
- }
- else if (m)
- {
- d = fbIn (src, m);
- *dst = fbOver24 (d, *dst);
- }
- dst++;
- }
- }
-}
-
-static void
-_XftSmoothGlyphGray565 (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- CARD32 src, srca;
- CARD32 r, g, b;
- CARD32 d;
- CARD16 *dstLine, *dst;
- CARD8 *maskLine, *mask, m;
- int dstStride, maskStride;
- int width, height;
- int w;
-
- srca = color->color.alpha >> 8;
-
- /* This handles only RGB and BGR */
- g = (color->color.green & 0xff00);
- if (image->red_mask == 0xf800)
- {
- r = (color->color.red & 0xff00) << 8;
- b = color->color.blue >> 8;
- }
- else
- {
- r = color->color.red >> 8;
- b = (color->color.blue & 0xff00) << 8;
- }
- src = (srca << 24) | r | g | b;
-
- width = xftg->metrics.width;
- height = xftg->metrics.height;
-
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
-
- dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
- dstStride = image->bytes_per_line >> 1;
- maskLine = (unsigned char *) xftg->bitmap;
- maskStride = (width + 3) & ~3;
-
- while (height--)
- {
- dst = dstLine;
- dstLine += dstStride;
- mask = maskLine;
- maskLine += maskStride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- d = src;
- else
- {
- d = *dst;
- d = fbOver24 (src, cvt0565to8888(d));
- }
- *dst = cvt8888to0565(d);
- }
- else if (m)
- {
- d = *dst;
- d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
- *dst = cvt8888to0565(d);
- }
- dst++;
- }
- }
-}
-
-static void
-_XftSmoothGlyphGray555 (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- CARD32 src, srca;
- CARD32 r, g, b;
- CARD32 d;
- CARD16 *dstLine, *dst;
- CARD8 *maskLine, *mask, m;
- int dstStride, maskStride;
- int width, height;
- int w;
-
- srca = color->color.alpha >> 8;
-
- /* This handles only RGB and BGR */
- g = (color->color.green & 0xff00);
- if (image->red_mask == 0xf800)
- {
- r = (color->color.red & 0xff00) << 8;
- b = color->color.blue >> 8;
- }
- else
- {
- r = color->color.red >> 8;
- b = (color->color.blue & 0xff00) << 8;
- }
- src = (srca << 24) | r | g | b;
-
- width = xftg->metrics.width;
- height = xftg->metrics.height;
-
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
-
- dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
- dstStride = image->bytes_per_line >> 1;
- maskLine = (unsigned char *) xftg->bitmap;
- maskStride = (width + 3) & ~3;
-
- while (height--)
- {
- dst = dstLine;
- dstLine += dstStride;
- mask = maskLine;
- maskLine += maskStride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- d = src;
- else
- {
- d = *dst;
- d = fbOver24 (src, cvt0555to8888(d));
- }
- *dst = cvt8888to0555(d);
- }
- else if (m)
- {
- d = *dst;
- d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
- *dst = cvt8888to0555(d);
- }
- dst++;
- }
- }
-}
-
-static void
-_XftSmoothGlyphGray (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- CARD32 src, srca;
- int r_shift, r_len;
- int g_shift, g_len;
- int b_shift, b_len;
- CARD8 *maskLine, *mask, m;
- int maskStride;
- CARD32 d;
- unsigned long pixel;
- int width, height;
- int w, tx;
-
- srca = color->color.alpha >> 8;
- src = (srca << 24 |
- (color->color.red & 0xff00) << 8 |
- (color->color.green & 0xff00) |
- (color->color.blue) >> 8);
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
- width = xftg->metrics.width;
- height = xftg->metrics.height;
-
- maskLine = (unsigned char *) xftg->bitmap;
- maskStride = (width + 3) & ~3;
-
- _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
- _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
- _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
- while (height--)
- {
- mask = maskLine;
- maskLine += maskStride;
- w = width;
- tx = x;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- d = src;
- else
- {
- pixel = XGetPixel (image, tx, y);
- d = (_XftGetField (pixel, r_shift, r_len) << 16 |
- _XftGetField (pixel, g_shift, g_len) << 8 |
- _XftGetField (pixel, b_shift, b_len));
- d = fbOver24 (src, d);
- }
- pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
- _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
- _XftPutField ((d ) & 0xff, b_shift, b_len));
- XPutPixel (image, tx, y, pixel);
- }
- else if (m)
- {
- pixel = XGetPixel (image, tx, y);
- d = (_XftGetField (pixel, r_shift, r_len) << 16 |
- _XftGetField (pixel, g_shift, g_len) << 8 |
- _XftGetField (pixel, b_shift, b_len));
- d = fbOver24 (fbIn(src,m), d);
- pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
- _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
- _XftPutField ((d ) & 0xff, b_shift, b_len));
- XPutPixel (image, tx, y, pixel);
- }
- tx++;
- }
- y++;
- }
-}
-
-static void
-_XftSmoothGlyphRgba (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color)
-{
- CARD32 src, srca;
- int r_shift, r_len;
- int g_shift, g_len;
- int b_shift, b_len;
- CARD32 *mask, ma;
- CARD32 d;
- unsigned long pixel;
- int width, height;
- int w, tx;
-
- srca = color->color.alpha >> 8;
- src = (srca << 24 |
- (color->color.red & 0xff00) << 8 |
- (color->color.green & 0xff00) |
- (color->color.blue) >> 8);
- x -= xftg->metrics.x;
- y -= xftg->metrics.y;
- width = xftg->metrics.width;
- height = xftg->metrics.height;
-
- mask = (CARD32 *) xftg->bitmap;
-
- _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
- _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
- _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
- while (height--)
- {
- w = width;
- tx = x;
-
- while (w--)
- {
- ma = *mask++;
- if (ma == 0xffffffff)
- {
- if (srca == 0xff)
- d = src;
- else
- {
- pixel = XGetPixel (image, tx, y);
- d = (_XftGetField (pixel, r_shift, r_len) << 16 |
- _XftGetField (pixel, g_shift, g_len) << 8 |
- _XftGetField (pixel, b_shift, b_len));
- d = fbOver24 (src, d);
- }
- pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
- _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
- _XftPutField ((d ) & 0xff, b_shift, b_len));
- XPutPixel (image, tx, y, pixel);
- }
- else if (ma)
- {
- CARD32 m,n,o;
- pixel = XGetPixel (image, tx, y);
- d = (_XftGetField (pixel, r_shift, r_len) << 16 |
- _XftGetField (pixel, g_shift, g_len) << 8 |
- _XftGetField (pixel, b_shift, b_len));
-#define XftInOverC(src,srca,msk,dst,i,result) { \
- CARD16 __a = XftGet8(msk,i); \
- CARD32 __t, __ta; \
- CARD32 __i; \
- __t = XftIntMult (XftGet8(src,i), __a,__i); \
- __ta = (CARD8) ~XftIntMult (srca, __a,__i); \
- __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \
- __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
- result = __t << (i); \
-}
- XftInOverC(src,srca,ma,d,0,m);
- XftInOverC(src,srca,ma,d,8,n);
- XftInOverC(src,srca,ma,d,16,o);
- d = m | n | o;
- pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
- _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
- _XftPutField ((d ) & 0xff, b_shift, b_len));
- XPutPixel (image, tx, y, pixel);
- }
- tx++;
- }
- y++;
- }
-}
-
-static FcBool
-_XftSmoothGlyphPossible (XftDraw *draw)
-{
- if (!draw->visual)
- return FcFalse;
- if (draw->visual->class != TrueColor)
- return FcFalse;
- return FcTrue;
-}
-
-typedef void (*XftSmoothGlyph) (XImage *image,
- _Xconst XftGlyph *xftg,
- int x,
- int y,
- _Xconst XftColor *color);
-
-static XftSmoothGlyph
-_XftSmoothGlyphFind (XftDraw *draw, XftFont *public)
-{
- XftFontInt *font = (XftFontInt *) public;
-
- if (!font->info.antialias)
- return _XftSmoothGlyphMono;
- else switch (font->info.rgba) {
- case FC_RGBA_RGB:
- case FC_RGBA_BGR:
- case FC_RGBA_VRGB:
- case FC_RGBA_VBGR:
- return _XftSmoothGlyphRgba;
- default:
- switch (XftDrawBitsPerPixel (draw)) {
- case 32:
- if ((draw->visual->red_mask == 0xff0000 &&
- draw->visual->green_mask == 0x00ff00 &&
- draw->visual->blue_mask == 0x0000ff) ||
- (draw->visual->red_mask == 0x0000ff &&
- draw->visual->green_mask == 0x00ff00 &&
- draw->visual->blue_mask == 0xff0000))
- {
- return _XftSmoothGlyphGray8888;
- }
- break;
- case 16:
- if ((draw->visual->red_mask == 0xf800 &&
- draw->visual->green_mask == 0x07e0 &&
- draw->visual->blue_mask == 0x001f) ||
- (draw->visual->red_mask == 0x001f &&
- draw->visual->green_mask == 0x07e0 &&
- draw->visual->blue_mask == 0xf800))
- {
- return _XftSmoothGlyphGray565;
- }
- if ((draw->visual->red_mask == 0x7c00 &&
- draw->visual->green_mask == 0x03e0 &&
- draw->visual->blue_mask == 0x001f) ||
- (draw->visual->red_mask == 0x001f &&
- draw->visual->green_mask == 0x03e0 &&
- draw->visual->blue_mask == 0x7c00))
- {
- return _XftSmoothGlyphGray555;
- }
- break;
- default:
- break;
- }
- return _XftSmoothGlyphGray;
- }
-}
-
-static XftGlyph *
-_XftGlyphDefault (Display *dpy, XftFont *public)
-{
- XftFontInt *font = (XftFontInt *) public;
- FT_UInt missing[XFT_NMISSING];
- int nmissing;
- FcBool glyphs_loaded = FcFalse;
-
- if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing))
- glyphs_loaded = FcTrue;
- if (nmissing)
- XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing);
- return font->glyphs[0];
-}
-
-static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event)
-{
- return 0;
-}
-
-_X_HIDDEN void
-XftGlyphCore (XftDraw *draw,
- _Xconst XftColor *color,
- XftFont *public,
- int x,
- int y,
- _Xconst FT_UInt *glyphs,
- int nglyphs)
-{
- Display *dpy = draw->dpy;
- XftFontInt *font = (XftFontInt *) public;
- XftGlyph *xftg;
- FT_UInt glyph;
- _Xconst FT_UInt *g;
- FT_UInt missing[XFT_NMISSING];
- FcBool glyphs_loaded;
- int nmissing;
- int n;
- XErrorHandler prev_error;
-
- /*
- * Load missing glyphs
- */
- g = glyphs;
- n = nglyphs;
- nmissing = 0;
- glyphs_loaded = FcFalse;
- while (n--)
- if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing))
- glyphs_loaded = FcTrue;
- if (nmissing)
- XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
-
- g = glyphs;
- n = nglyphs;
- if ((font->info.antialias || color->color.alpha != 0xffff) &&
- _XftSmoothGlyphPossible (draw))
- {
- XGlyphInfo gi;
- XImage *image;
- unsigned int depth;
- int ox, oy;
- XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
-
- XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
- if (!gi.width || !gi.height)
- goto bail1;
- ox = x - gi.x;
- oy = y - gi.y;
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- ox, oy,
- gi.width, gi.height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = NULL;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
-
- pix = XCreatePixmap (dpy, draw->drawable,
- gi.width, gi.height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
- gi.width, gi.height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
- if (!image)
- goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- while (n--)
- {
- glyph = *g++;
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- {
- (*smooth) (image, xftg, x - ox, y - oy, color);
- x += xftg->metrics.xOff;
- y += xftg->metrics.yOff;
- }
- }
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
- gi.width, gi.height);
- XDestroyImage (image);
- }
- else
- {
- XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
- while (n--)
- {
- glyph = *g++;
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- {
- (*sharp) (draw, xftg, x, y);
- x += xftg->metrics.xOff;
- y += xftg->metrics.yOff;
- }
- }
- }
-bail1:
- if (glyphs_loaded)
- _XftFontManageMemory (dpy, public);
-}
-
-#define NUM_LOCAL 1024
-
-_X_HIDDEN void
-XftGlyphSpecCore (XftDraw *draw,
- _Xconst XftColor *color,
- XftFont *public,
- _Xconst XftGlyphSpec *glyphs,
- int nglyphs)
-{
- Display *dpy = draw->dpy;
- XftFontInt *font = (XftFontInt *) public;
- XftGlyph *xftg;
- FT_UInt missing[XFT_NMISSING];
- FcBool glyphs_loaded;
- int nmissing;
- int i;
- XErrorHandler prev_error;
- int x1, y1, x2, y2;
-
- /*
- * Load missing glyphs
- */
- glyphs_loaded = FcFalse;
- x1 = y1 = x2 = y2 = 0;
- for (i = 0; i < nglyphs; i++)
- {
- XGlyphInfo gi;
- int g_x1, g_x2, g_y1, g_y2;
-
- nmissing = 0;
- if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
- glyphs_loaded = FcTrue;
- if (nmissing)
- XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
-
- XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
- g_x1 = glyphs[i].x - gi.x;
- g_y1 = glyphs[i].y - gi.y;
- g_x2 = g_x1 + gi.width;
- g_y2 = g_y1 + gi.height;
- if (i)
- {
- if (g_x1 < x1)
- x1 = g_x1;
- if (g_y1 < y1)
- y1 = g_y1;
- if (g_x2 > x2)
- x2 = g_x2;
- if (g_y2 > y2)
- y2 = g_y2;
- }
- else
- {
- x1 = g_x1;
- y1 = g_y1;
- x2 = g_x2;
- y2 = g_y2;
- }
- }
-
- if (x1 == x2 || y1 == y2)
- goto bail1;
-
- if ((font->info.antialias || color->color.alpha != 0xffff) &&
- _XftSmoothGlyphPossible (draw))
- {
- XImage *image;
- unsigned int depth;
- int width = x2 - x1, height = y2 - y1;
- XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
-
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- x1, y1,
- width, height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = NULL;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
-
- pix = XCreatePixmap (dpy, draw->drawable,
- width, height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
- width, height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
- if (!image)
- goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- for (i = 0; i < nglyphs; i++)
- {
- FT_UInt glyph = glyphs[i].glyph;
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- {
- (*smooth) (image, xftg, glyphs[i].x - x1,
- glyphs[i].y - y1, color);
- }
- }
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
- width, height);
- XDestroyImage (image);
- }
- else
- {
- XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
- for (i = 0; i < nglyphs; i++)
- {
- FT_UInt glyph = glyphs[i].glyph;
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
- }
- }
-bail1:
- if (glyphs_loaded)
- _XftFontManageMemory (dpy, public);
-}
-
-_X_HIDDEN void
-XftGlyphFontSpecCore (XftDraw *draw,
- _Xconst XftColor *color,
- _Xconst XftGlyphFontSpec *glyphs,
- int nglyphs)
-{
- Display *dpy = draw->dpy;
- XftGlyph *xftg;
- FT_UInt missing[XFT_NMISSING];
- FcBool glyphs_loaded;
- int nmissing;
- int i;
- XErrorHandler prev_error;
- int x1, y1, x2, y2;
-
- /*
- * Load missing glyphs
- */
- glyphs_loaded = FcFalse;
- x1 = y1 = x2 = y2 = 0;
- for (i = 0; i < nglyphs; i++)
- {
- XftFont *public = glyphs[i].font;
- XGlyphInfo gi;
- int g_x1, g_x2, g_y1, g_y2;
-
- nmissing = 0;
- if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
- glyphs_loaded = FcTrue;
- if (nmissing)
- XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
-
- XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
- g_x1 = glyphs[i].x - gi.x;
- g_y1 = glyphs[i].y - gi.y;
- g_x2 = g_x1 + gi.width;
- g_y2 = g_y1 + gi.height;
- if (i)
- {
- if (g_x1 < x1)
- x1 = g_x1;
- if (g_y1 < y1)
- y1 = g_y1;
- if (g_x2 > x2)
- x2 = g_x2;
- if (g_y2 > y2)
- y2 = g_y2;
- }
- else
- {
- x1 = g_x1;
- y1 = g_y1;
- x2 = g_x2;
- y2 = g_y2;
- }
- }
-
- if (x1 == x2 || y1 == y2)
- goto bail1;
-
- for (i = 0; i < nglyphs; i++)
- if (((XftFontInt *) glyphs[i].font)->info.antialias)
- break;
-
- if ((i != nglyphs || color->color.alpha != 0xffff) &&
- _XftSmoothGlyphPossible (draw))
- {
- XImage *image;
- unsigned int depth;
- int width = x2 - x1, height = y2 - y1;
-
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- x1, y1,
- width, height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = NULL;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
-
- pix = XCreatePixmap (dpy, draw->drawable,
- width, height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
- width, height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
- if (!image)
- goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- for (i = 0; i < nglyphs; i++)
- {
- XftFont *public = glyphs[i].font;
- XftFontInt *font = (XftFontInt *) public;
- XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
- FT_UInt glyph = glyphs[i].glyph;
-
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- {
- (*smooth) (image, xftg, glyphs[i].x - x1,
- glyphs[i].y - y1, color);
- }
- }
- if (image->byte_order != XftNativeByteOrder ())
- XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
- width, height);
- XDestroyImage (image);
- }
- else
- {
- for (i = 0; i < nglyphs; i++)
- {
- XftFont *public = glyphs[i].font;
- XftFontInt *font = (XftFontInt *) public;
- XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
- FT_UInt glyph = glyphs[i].glyph;
-
- if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
- xftg = _XftGlyphDefault (dpy, public);
- if (xftg)
- (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
- }
- }
-bail1:
- if (glyphs_loaded)
- for (i = 0; i < nglyphs; i++)
- _XftFontManageMemory (dpy, glyphs[i].font);
-}
+/*
+ * 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"
+
+_X_HIDDEN void
+XftRectCore (XftDraw *draw,
+ _Xconst XftColor *color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ if (color->color.alpha >= 0x8000)
+ {
+ XSetForeground (draw->dpy, draw->core.gc, color->pixel);
+ XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
+ x, y, width, height);
+ }
+}
+
+/*
+ * Use the core protocol to draw the glyphs
+ */
+
+static void
+_XftSharpGlyphMono (XftDraw *draw,
+ XftGlyph *glyph,
+ int x,
+ int y)
+{
+ unsigned char *srcLine = glyph->bitmap, *src;
+ unsigned char bits, bitsMask;
+ int width = glyph->metrics.width;
+ int stride = ((width + 31) & ~31) >> 3;
+ int height = glyph->metrics.height;
+ int w;
+ int xspan, lenspan;
+
+ x -= glyph->metrics.x;
+ y -= glyph->metrics.y;
+ while (height--)
+ {
+ src = srcLine;
+ srcLine += stride;
+ w = width;
+
+ bitsMask = 0x80; /* FreeType is always MSB first */
+ bits = *src++;
+
+ xspan = x;
+ while (w)
+ {
+ if (bits & bitsMask)
+ {
+ lenspan = 0;
+ do
+ {
+ lenspan++;
+ if (lenspan == w)
+ break;
+ bitsMask = bitsMask >> 1;
+ if (!bitsMask)
+ {
+ bits = *src++;
+ bitsMask = 0x80;
+ }
+ } while (bits & bitsMask);
+ XFillRectangle (draw->dpy, draw->drawable,
+ draw->core.gc, xspan, y, lenspan, 1);
+ xspan += lenspan;
+ w -= lenspan;
+ }
+ else
+ {
+ do
+ {
+ w--;
+ xspan++;
+ if (!w)
+ break;
+ bitsMask = bitsMask >> 1;
+ if (!bitsMask)
+ {
+ bits = *src++;
+ bitsMask = 0x80;
+ }
+ } while (!(bits & bitsMask));
+ }
+ }
+ y++;
+ }
+}
+
+/*
+ * Draw solid color text from an anti-aliased bitmap. This is a
+ * fallback for cases where a particular drawable has no AA code
+ */
+static void
+_XftSharpGlyphGray (XftDraw *draw,
+ XftGlyph *glyph,
+ int x,
+ int y)
+{
+ unsigned char *srcLine = glyph->bitmap, *src, bits;
+ int width = glyph->metrics.width;
+ int stride = ((width + 3) & ~3);
+ int height = glyph->metrics.height;
+ int w;
+ int xspan, lenspan;
+
+ x -= glyph->metrics.x;
+ y -= glyph->metrics.y;
+ while (height--)
+ {
+ src = srcLine;
+ srcLine += stride;
+ w = width;
+
+ bits = *src++;
+ xspan = x;
+ while (w)
+ {
+ if (bits >= 0x80)
+ {
+ lenspan = 0;
+ do
+ {
+ lenspan++;
+ if (lenspan == w)
+ break;
+ bits = *src++;
+ } while (bits >= 0x80);
+ XFillRectangle (draw->dpy, draw->drawable,
+ draw->core.gc, xspan, y, lenspan, 1);
+ xspan += lenspan;
+ w -= lenspan;
+ }
+ else
+ {
+ do
+ {
+ w--;
+ xspan++;
+ if (!w)
+ break;
+ bits = *src++;
+ } while (bits < 0x80);
+ }
+ }
+ y++;
+ }
+}
+
+static void
+_XftSharpGlyphRgba (XftDraw *draw,
+ XftGlyph *glyph,
+ int x,
+ int y)
+{
+ CARD32 *srcLine = glyph->bitmap, *src, bits;
+ int width = glyph->metrics.width;
+ int stride = ((width + 3) & ~3);
+ int height = glyph->metrics.height;
+ int w;
+ int xspan, lenspan;
+
+ x -= glyph->metrics.x;
+ y -= glyph->metrics.y;
+ while (height--)
+ {
+ src = srcLine;
+ srcLine += stride;
+ w = width;
+
+ bits = *src++;
+ xspan = x;
+ while (w)
+ {
+ if (bits >= 0x80000000)
+ {
+ lenspan = 0;
+ do
+ {
+ lenspan++;
+ if (lenspan == w)
+ break;
+ bits = *src++;
+ } while (bits >= 0x80000000);
+ XFillRectangle (draw->dpy, draw->drawable,
+ draw->core.gc, xspan, y, lenspan, 1);
+ xspan += lenspan;
+ w -= lenspan;
+ }
+ else
+ {
+ do
+ {
+ w--;
+ xspan++;
+ if (!w)
+ break;
+ bits = *src++;
+ } while (bits < 0x80000000);
+ }
+ }
+ y++;
+ }
+}
+
+typedef void (*XftSharpGlyph) (XftDraw *draw,
+ XftGlyph *glyph,
+ int x,
+ int y);
+
+static XftSharpGlyph
+_XftSharpGlyphFind (XftDraw *draw, XftFont *public)
+{
+ XftFontInt *font = (XftFontInt *) public;
+
+ if (!font->info.antialias)
+ return _XftSharpGlyphMono;
+ else switch (font->info.rgba) {
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ return _XftSharpGlyphRgba;
+ default:
+ return _XftSharpGlyphGray;
+ }
+}
+
+/*
+ * Draw glyphs to a target that supports anti-aliasing
+ */
+
+/*
+ * Primitives for converting between RGB values and TrueColor pixels
+ */
+
+static void
+_XftExamineBitfield (unsigned long mask, int *shift, int *len)
+{
+ int s, l;
+
+ s = 0;
+ while ((mask & 1) == 0)
+ {
+ mask >>= 1;
+ s++;
+ }
+ l = 0;
+ while ((mask & 1) == 1)
+ {
+ mask >>= 1;
+ l++;
+ }
+ *shift = s;
+ *len = l;
+}
+
+static CARD32
+_XftGetField (unsigned long l_pixel, int shift, int len)
+{
+ CARD32 pixel = (CARD32) l_pixel;
+
+ pixel = pixel & (((1 << (len)) - 1) << shift);
+ pixel = pixel << (32 - (shift + len)) >> 24;
+ while (len < 8)
+ {
+ pixel |= (pixel >> len);
+ len <<= 1;
+ }
+ return pixel;
+}
+
+static unsigned long
+_XftPutField (CARD32 pixel, int shift, int len)
+{
+ unsigned long l_pixel = (unsigned long) pixel;
+
+ shift = shift - (8 - len);
+ if (len <= 8)
+ l_pixel &= (((1 << len) - 1) << (8 - len));
+ if (shift < 0)
+ l_pixel >>= -shift;
+ else
+ l_pixel <<= shift;
+ return l_pixel;
+}
+
+/*
+ * This is used when doing XftCharFontSpec/XftGlyphFontSpec where
+ * some of the fonts are bitmaps and some are anti-aliased to handle
+ * the bitmap portions
+ */
+static void
+_XftSmoothGlyphMono (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ unsigned char *srcLine = xftg->bitmap, *src;
+ unsigned char bits, bitsMask;
+ int width = xftg->metrics.width;
+ int stride = ((width + 31) & ~31) >> 3;
+ int height = xftg->metrics.height;
+ int w;
+ int xspan;
+ int r_shift, r_len;
+ int g_shift, g_len;
+ int b_shift, b_len;
+ unsigned long pixel;
+
+ _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
+ _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
+ _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
+ pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) |
+ _XftPutField (color->color.green >> 8, g_shift, g_len) |
+ _XftPutField (color->color.blue >> 8, b_shift, b_len));
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+ while (height--)
+ {
+ src = srcLine;
+ srcLine += stride;
+ w = width;
+
+ bitsMask = 0x80; /* FreeType is always MSB first */
+ bits = *src++;
+
+ xspan = x;
+ while (w--)
+ {
+ if (bits & bitsMask)
+ XPutPixel (image, xspan, y, pixel);
+ bitsMask = bitsMask >> 1;
+ if (!bitsMask)
+ {
+ bits = *src++;
+ bitsMask = 0x80;
+ }
+ xspan++;
+ }
+ y++;
+ }
+}
+
+/*
+ * As simple anti-aliasing is likely to be common, there are three
+ * optimized versions for the usual true color pixel formats (888, 565, 555).
+ * Other formats are handled by the general case
+ */
+
+#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \
+ (((s) >> 5) & 0x07e0) | \
+ (((s) >> 8) & 0xf800))
+
+#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
+ ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
+ ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
+
+#define cvt8888to0555(s) ((((s) >> 3) & 0x001f) | \
+ (((s) >> 6) & 0x03e0) | \
+ (((s) >> 7) & 0x7c00))
+
+#define cvt0555to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
+ ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
+ ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
+
+
+#define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
+#define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b))
+
+#define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i))
+
+/*
+ * There are two ways of handling alpha -- either as a single unified value or
+ * a separate value for each component, hence each macro must have two
+ * versions. The unified alpha version has a 'U' at the end of the name,
+ * the component version has a 'C'. Similarly, functions which deal with
+ * this difference will have two versions using the same convention.
+ */
+
+#define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\
+ (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+#define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\
+ (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+#define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i))
+
+#define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i))
+
+#define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \
+ XftIntMult(XftGet8(x,i),ax,(v))),\
+ (CARD32) ((CARD8) ((t) | \
+ (0 - ((t) >> 8)))) << (i))
+
+#define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \
+ (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+
+static CARD32
+fbOver24 (CARD32 x, CARD32 y)
+{
+ CARD16 a = ~x >> 24;
+ CARD16 t;
+ CARD32 m,n,o;
+
+ m = XftOverU(x,y,0,a,t);
+ n = XftOverU(x,y,8,a,t);
+ o = XftOverU(x,y,16,a,t);
+ return m|n|o;
+}
+
+static CARD32
+fbIn (CARD32 x, CARD8 y)
+{
+ CARD16 a = y;
+ CARD16 t;
+ CARD32 m,n,o,p;
+
+ m = XftInU(x,0,a,t);
+ n = XftInU(x,8,a,t);
+ o = XftInU(x,16,a,t);
+ p = XftInU(x,24,a,t);
+ return m|n|o|p;
+}
+
+static void
+_XftSmoothGlyphGray8888 (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ CARD32 src, srca;
+ CARD32 r, g, b;
+ CARD32 *dstLine, *dst, d;
+ CARD8 *maskLine, *mask, m;
+ int dstStride, maskStride;
+ int width, height;
+ int w;
+
+ srca = color->color.alpha >> 8;
+
+ /* This handles only RGB and BGR */
+ g = (color->color.green & 0xff00);
+ if (image->red_mask == 0xff0000)
+ {
+ r = (color->color.red & 0xff00) << 8;
+ b = color->color.blue >> 8;
+ }
+ else
+ {
+ r = color->color.red >> 8;
+ b = (color->color.blue & 0xff00) << 8;
+ }
+ src = (srca << 24) | r | g | b;
+
+ width = xftg->metrics.width;
+ height = xftg->metrics.height;
+
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+
+ dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2));
+ dstStride = image->bytes_per_line >> 2;
+ maskLine = (unsigned char *) xftg->bitmap;
+ maskStride = (width + 3) & ~3;
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ *dst = src;
+ else
+ *dst = fbOver24 (src, *dst);
+ }
+ else if (m)
+ {
+ d = fbIn (src, m);
+ *dst = fbOver24 (d, *dst);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+_XftSmoothGlyphGray565 (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ CARD32 src, srca;
+ CARD32 r, g, b;
+ CARD32 d;
+ CARD16 *dstLine, *dst;
+ CARD8 *maskLine, *mask, m;
+ int dstStride, maskStride;
+ int width, height;
+ int w;
+
+ srca = color->color.alpha >> 8;
+
+ /* This handles only RGB and BGR */
+ g = (color->color.green & 0xff00);
+ if (image->red_mask == 0xf800)
+ {
+ r = (color->color.red & 0xff00) << 8;
+ b = color->color.blue >> 8;
+ }
+ else
+ {
+ r = color->color.red >> 8;
+ b = (color->color.blue & 0xff00) << 8;
+ }
+ src = (srca << 24) | r | g | b;
+
+ width = xftg->metrics.width;
+ height = xftg->metrics.height;
+
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+
+ dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
+ dstStride = image->bytes_per_line >> 1;
+ maskLine = (unsigned char *) xftg->bitmap;
+ maskStride = (width + 3) & ~3;
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ d = src;
+ else
+ {
+ d = *dst;
+ d = fbOver24 (src, cvt0565to8888(d));
+ }
+ *dst = cvt8888to0565(d);
+ }
+ else if (m)
+ {
+ d = *dst;
+ d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
+ *dst = cvt8888to0565(d);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+_XftSmoothGlyphGray555 (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ CARD32 src, srca;
+ CARD32 r, g, b;
+ CARD32 d;
+ CARD16 *dstLine, *dst;
+ CARD8 *maskLine, *mask, m;
+ int dstStride, maskStride;
+ int width, height;
+ int w;
+
+ srca = color->color.alpha >> 8;
+
+ /* This handles only RGB and BGR */
+ g = (color->color.green & 0xff00);
+ if (image->red_mask == 0xf800)
+ {
+ r = (color->color.red & 0xff00) << 8;
+ b = color->color.blue >> 8;
+ }
+ else
+ {
+ r = color->color.red >> 8;
+ b = (color->color.blue & 0xff00) << 8;
+ }
+ src = (srca << 24) | r | g | b;
+
+ width = xftg->metrics.width;
+ height = xftg->metrics.height;
+
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+
+ dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
+ dstStride = image->bytes_per_line >> 1;
+ maskLine = (unsigned char *) xftg->bitmap;
+ maskStride = (width + 3) & ~3;
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ d = src;
+ else
+ {
+ d = *dst;
+ d = fbOver24 (src, cvt0555to8888(d));
+ }
+ *dst = cvt8888to0555(d);
+ }
+ else if (m)
+ {
+ d = *dst;
+ d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
+ *dst = cvt8888to0555(d);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+_XftSmoothGlyphGray (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ CARD32 src, srca;
+ int r_shift, r_len;
+ int g_shift, g_len;
+ int b_shift, b_len;
+ CARD8 *maskLine, *mask, m;
+ int maskStride;
+ CARD32 d;
+ unsigned long pixel;
+ int width, height;
+ int w, tx;
+
+ srca = color->color.alpha >> 8;
+ src = (srca << 24 |
+ (color->color.red & 0xff00) << 8 |
+ (color->color.green & 0xff00) |
+ (color->color.blue) >> 8);
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+ width = xftg->metrics.width;
+ height = xftg->metrics.height;
+
+ maskLine = (unsigned char *) xftg->bitmap;
+ maskStride = (width + 3) & ~3;
+
+ _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
+ _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
+ _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
+ while (height--)
+ {
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+ tx = x;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ d = src;
+ else
+ {
+ pixel = XGetPixel (image, tx, y);
+ d = (_XftGetField (pixel, r_shift, r_len) << 16 |
+ _XftGetField (pixel, g_shift, g_len) << 8 |
+ _XftGetField (pixel, b_shift, b_len));
+ d = fbOver24 (src, d);
+ }
+ pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
+ _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
+ _XftPutField ((d ) & 0xff, b_shift, b_len));
+ XPutPixel (image, tx, y, pixel);
+ }
+ else if (m)
+ {
+ pixel = XGetPixel (image, tx, y);
+ d = (_XftGetField (pixel, r_shift, r_len) << 16 |
+ _XftGetField (pixel, g_shift, g_len) << 8 |
+ _XftGetField (pixel, b_shift, b_len));
+ d = fbOver24 (fbIn(src,m), d);
+ pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
+ _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
+ _XftPutField ((d ) & 0xff, b_shift, b_len));
+ XPutPixel (image, tx, y, pixel);
+ }
+ tx++;
+ }
+ y++;
+ }
+}
+
+static void
+_XftSmoothGlyphRgba (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color)
+{
+ CARD32 src, srca;
+ int r_shift, r_len;
+ int g_shift, g_len;
+ int b_shift, b_len;
+ CARD32 *mask, ma;
+ CARD32 d;
+ unsigned long pixel;
+ int width, height;
+ int w, tx;
+
+ srca = color->color.alpha >> 8;
+ src = (srca << 24 |
+ (color->color.red & 0xff00) << 8 |
+ (color->color.green & 0xff00) |
+ (color->color.blue) >> 8);
+ x -= xftg->metrics.x;
+ y -= xftg->metrics.y;
+ width = xftg->metrics.width;
+ height = xftg->metrics.height;
+
+ mask = (CARD32 *) xftg->bitmap;
+
+ _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
+ _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
+ _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
+ while (height--)
+ {
+ w = width;
+ tx = x;
+
+ while (w--)
+ {
+ ma = *mask++;
+ if (ma == 0xffffffff)
+ {
+ if (srca == 0xff)
+ d = src;
+ else
+ {
+ pixel = XGetPixel (image, tx, y);
+ d = (_XftGetField (pixel, r_shift, r_len) << 16 |
+ _XftGetField (pixel, g_shift, g_len) << 8 |
+ _XftGetField (pixel, b_shift, b_len));
+ d = fbOver24 (src, d);
+ }
+ pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
+ _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
+ _XftPutField ((d ) & 0xff, b_shift, b_len));
+ XPutPixel (image, tx, y, pixel);
+ }
+ else if (ma)
+ {
+ CARD32 m,n,o;
+ pixel = XGetPixel (image, tx, y);
+ d = (_XftGetField (pixel, r_shift, r_len) << 16 |
+ _XftGetField (pixel, g_shift, g_len) << 8 |
+ _XftGetField (pixel, b_shift, b_len));
+#define XftInOverC(src,srca,msk,dst,i,result) { \
+ CARD16 __a = XftGet8(msk,i); \
+ CARD32 __t, __ta; \
+ CARD32 __i; \
+ __t = XftIntMult (XftGet8(src,i), __a,__i); \
+ __ta = (CARD8) ~XftIntMult (srca, __a,__i); \
+ __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \
+ __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
+ result = __t << (i); \
+}
+ XftInOverC(src,srca,ma,d,0,m);
+ XftInOverC(src,srca,ma,d,8,n);
+ XftInOverC(src,srca,ma,d,16,o);
+ d = m | n | o;
+ pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
+ _XftPutField ((d >> 8) & 0xff, g_shift, g_len) |
+ _XftPutField ((d ) & 0xff, b_shift, b_len));
+ XPutPixel (image, tx, y, pixel);
+ }
+ tx++;
+ }
+ y++;
+ }
+}
+
+static FcBool
+_XftSmoothGlyphPossible (XftDraw *draw)
+{
+ if (!draw->visual)
+ return FcFalse;
+ if (draw->visual->class != TrueColor)
+ return FcFalse;
+ return FcTrue;
+}
+
+typedef void (*XftSmoothGlyph) (XImage *image,
+ _Xconst XftGlyph *xftg,
+ int x,
+ int y,
+ _Xconst XftColor *color);
+
+static XftSmoothGlyph
+_XftSmoothGlyphFind (XftDraw *draw, XftFont *public)
+{
+ XftFontInt *font = (XftFontInt *) public;
+
+ if (!font->info.antialias)
+ return _XftSmoothGlyphMono;
+ else switch (font->info.rgba) {
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ return _XftSmoothGlyphRgba;
+ default:
+ switch (XftDrawBitsPerPixel (draw)) {
+ case 32:
+ if ((draw->visual->red_mask == 0xff0000 &&
+ draw->visual->green_mask == 0x00ff00 &&
+ draw->visual->blue_mask == 0x0000ff) ||
+ (draw->visual->red_mask == 0x0000ff &&
+ draw->visual->green_mask == 0x00ff00 &&
+ draw->visual->blue_mask == 0xff0000))
+ {
+ return _XftSmoothGlyphGray8888;
+ }
+ break;
+ case 16:
+ if ((draw->visual->red_mask == 0xf800 &&
+ draw->visual->green_mask == 0x07e0 &&
+ draw->visual->blue_mask == 0x001f) ||
+ (draw->visual->red_mask == 0x001f &&
+ draw->visual->green_mask == 0x07e0 &&
+ draw->visual->blue_mask == 0xf800))
+ {
+ return _XftSmoothGlyphGray565;
+ }
+ if ((draw->visual->red_mask == 0x7c00 &&
+ draw->visual->green_mask == 0x03e0 &&
+ draw->visual->blue_mask == 0x001f) ||
+ (draw->visual->red_mask == 0x001f &&
+ draw->visual->green_mask == 0x03e0 &&
+ draw->visual->blue_mask == 0x7c00))
+ {
+ return _XftSmoothGlyphGray555;
+ }
+ break;
+ default:
+ break;
+ }
+ return _XftSmoothGlyphGray;
+ }
+}
+
+static XftGlyph *
+_XftGlyphDefault (Display *dpy, XftFont *public)
+{
+ XftFontInt *font = (XftFontInt *) public;
+ FT_UInt missing[XFT_NMISSING];
+ int nmissing;
+ FcBool glyphs_loaded = FcFalse;
+
+ if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing))
+ glyphs_loaded = FcTrue;
+ if (nmissing)
+ XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing);
+ return font->glyphs[0];
+}
+
+static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event)
+{
+ return 0;
+}
+
+_X_HIDDEN void
+XftGlyphCore (XftDraw *draw,
+ _Xconst XftColor *color,
+ XftFont *public,
+ int x,
+ int y,
+ _Xconst FT_UInt *glyphs,
+ int nglyphs)
+{
+ Display *dpy = draw->dpy;
+ XftFontInt *font = (XftFontInt *) public;
+ XftGlyph *xftg;
+ FT_UInt glyph;
+ _Xconst FT_UInt *g;
+ FT_UInt missing[XFT_NMISSING];
+ FcBool glyphs_loaded;
+ int nmissing;
+ int n;
+ XErrorHandler prev_error;
+
+ /*
+ * Load missing glyphs
+ */
+ g = glyphs;
+ n = nglyphs;
+ nmissing = 0;
+ glyphs_loaded = FcFalse;
+ while (n--)
+ if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing))
+ glyphs_loaded = FcTrue;
+ if (nmissing)
+ XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
+
+ g = glyphs;
+ n = nglyphs;
+ if ((font->info.antialias || color->color.alpha != 0xffff) &&
+ _XftSmoothGlyphPossible (draw))
+ {
+ XGlyphInfo gi;
+ XImage *image;
+ unsigned int depth;
+ int ox, oy;
+ XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
+
+ XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
+ if (!gi.width || !gi.height)
+ goto bail1;
+ ox = x - gi.x;
+ oy = y - gi.y;
+ /*
+ * Try to get bits directly from the drawable; if that fails,
+ * use a temporary pixmap. When it does fail, assume it
+ * will probably fail for a while and keep using temporary
+ * pixmaps for a while to avoid double round trips.
+ */
+ if (draw->core.use_pixmap == 0)
+ {
+ prev_error = XSetErrorHandler (XftGetImageErrorHandler);
+ image = XGetImage (dpy, draw->drawable,
+ ox, oy,
+ gi.width, gi.height, AllPlanes,
+ ZPixmap);
+ XSetErrorHandler (prev_error);
+ if (!image)
+ draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
+ }
+ else
+ {
+ draw->core.use_pixmap--;
+ image = NULL;
+ }
+ if (!image && (depth = XftDrawDepth (draw)))
+ {
+ Pixmap pix;
+ GC gc;
+ XGCValues gcv;
+
+ pix = XCreatePixmap (dpy, draw->drawable,
+ gi.width, gi.height, depth);
+ gcv.graphics_exposures = False;
+ gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
+ XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
+ gi.width, gi.height, 0, 0);
+ XFreeGC (dpy, gc);
+ image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
+ ZPixmap);
+ XFreePixmap (dpy, pix);
+ }
+ if (!image)
+ goto bail1;
+ image->red_mask = draw->visual->red_mask;
+ image->green_mask = draw->visual->green_mask;
+ image->blue_mask = draw->visual->blue_mask;
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ while (n--)
+ {
+ glyph = *g++;
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ {
+ (*smooth) (image, xftg, x - ox, y - oy, color);
+ x += xftg->metrics.xOff;
+ y += xftg->metrics.yOff;
+ }
+ }
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
+ gi.width, gi.height);
+ XDestroyImage (image);
+ }
+ else
+ {
+ XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
+ while (n--)
+ {
+ glyph = *g++;
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ {
+ (*sharp) (draw, xftg, x, y);
+ x += xftg->metrics.xOff;
+ y += xftg->metrics.yOff;
+ }
+ }
+ }
+bail1:
+ if (glyphs_loaded)
+ _XftFontManageMemory (dpy, public);
+}
+
+#define NUM_LOCAL 1024
+
+_X_HIDDEN void
+XftGlyphSpecCore (XftDraw *draw,
+ _Xconst XftColor *color,
+ XftFont *public,
+ _Xconst XftGlyphSpec *glyphs,
+ int nglyphs)
+{
+ Display *dpy = draw->dpy;
+ XftFontInt *font = (XftFontInt *) public;
+ XftGlyph *xftg;
+ FT_UInt missing[XFT_NMISSING];
+ FcBool glyphs_loaded;
+ int nmissing;
+ int i;
+ XErrorHandler prev_error;
+ int x1, y1, x2, y2;
+
+ /*
+ * Load missing glyphs
+ */
+ glyphs_loaded = FcFalse;
+ x1 = y1 = x2 = y2 = 0;
+ for (i = 0; i < nglyphs; i++)
+ {
+ XGlyphInfo gi;
+ int g_x1, g_x2, g_y1, g_y2;
+
+ nmissing = 0;
+ if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
+ glyphs_loaded = FcTrue;
+ if (nmissing)
+ XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
+
+ XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
+ g_x1 = glyphs[i].x - gi.x;
+ g_y1 = glyphs[i].y - gi.y;
+ g_x2 = g_x1 + gi.width;
+ g_y2 = g_y1 + gi.height;
+ if (i)
+ {
+ if (g_x1 < x1)
+ x1 = g_x1;
+ if (g_y1 < y1)
+ y1 = g_y1;
+ if (g_x2 > x2)
+ x2 = g_x2;
+ if (g_y2 > y2)
+ y2 = g_y2;
+ }
+ else
+ {
+ x1 = g_x1;
+ y1 = g_y1;
+ x2 = g_x2;
+ y2 = g_y2;
+ }
+ }
+
+ if (x1 == x2 || y1 == y2)
+ goto bail1;
+
+ if ((font->info.antialias || color->color.alpha != 0xffff) &&
+ _XftSmoothGlyphPossible (draw))
+ {
+ XImage *image;
+ unsigned int depth;
+ int width = x2 - x1, height = y2 - y1;
+ XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
+
+ /*
+ * Try to get bits directly from the drawable; if that fails,
+ * use a temporary pixmap. When it does fail, assume it
+ * will probably fail for a while and keep using temporary
+ * pixmaps for a while to avoid double round trips.
+ */
+ if (draw->core.use_pixmap == 0)
+ {
+ prev_error = XSetErrorHandler (XftGetImageErrorHandler);
+ image = XGetImage (dpy, draw->drawable,
+ x1, y1,
+ width, height, AllPlanes,
+ ZPixmap);
+ XSetErrorHandler (prev_error);
+ if (!image)
+ draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
+ }
+ else
+ {
+ draw->core.use_pixmap--;
+ image = NULL;
+ }
+ if (!image && (depth = XftDrawDepth (draw)))
+ {
+ Pixmap pix;
+ GC gc;
+ XGCValues gcv;
+
+ pix = XCreatePixmap (dpy, draw->drawable,
+ width, height, depth);
+ gcv.graphics_exposures = False;
+ gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
+ XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
+ width, height, 0, 0);
+ XFreeGC (dpy, gc);
+ image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
+ ZPixmap);
+ XFreePixmap (dpy, pix);
+ }
+ if (!image)
+ goto bail1;
+ image->red_mask = draw->visual->red_mask;
+ image->green_mask = draw->visual->green_mask;
+ image->blue_mask = draw->visual->blue_mask;
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ for (i = 0; i < nglyphs; i++)
+ {
+ FT_UInt glyph = glyphs[i].glyph;
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ {
+ (*smooth) (image, xftg, glyphs[i].x - x1,
+ glyphs[i].y - y1, color);
+ }
+ }
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
+ width, height);
+ XDestroyImage (image);
+ }
+ else
+ {
+ XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
+ for (i = 0; i < nglyphs; i++)
+ {
+ FT_UInt glyph = glyphs[i].glyph;
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
+ }
+ }
+bail1:
+ if (glyphs_loaded)
+ _XftFontManageMemory (dpy, public);
+}
+
+_X_HIDDEN void
+XftGlyphFontSpecCore (XftDraw *draw,
+ _Xconst XftColor *color,
+ _Xconst XftGlyphFontSpec *glyphs,
+ int nglyphs)
+{
+ Display *dpy = draw->dpy;
+ XftGlyph *xftg;
+ FT_UInt missing[XFT_NMISSING];
+ FcBool glyphs_loaded;
+ int nmissing;
+ int i;
+ XErrorHandler prev_error;
+ int x1, y1, x2, y2;
+
+ /*
+ * Load missing glyphs
+ */
+ glyphs_loaded = FcFalse;
+ x1 = y1 = x2 = y2 = 0;
+ for (i = 0; i < nglyphs; i++)
+ {
+ XftFont *public = glyphs[i].font;
+ XGlyphInfo gi;
+ int g_x1, g_x2, g_y1, g_y2;
+
+ nmissing = 0;
+ if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
+ glyphs_loaded = FcTrue;
+ if (nmissing)
+ XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
+
+ XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
+ g_x1 = glyphs[i].x - gi.x;
+ g_y1 = glyphs[i].y - gi.y;
+ g_x2 = g_x1 + gi.width;
+ g_y2 = g_y1 + gi.height;
+ if (i)
+ {
+ if (g_x1 < x1)
+ {
+ if (g_x1 < 0)
+ {
+ /* do nothing if the given glyphs are out of range */
+ short t = glyphs[i-1].font->max_advance_width
+ + glyphs[i-1].x;
+ if (t < 0 && glyphs[i-1].x > 0)
+ goto bail1;
+ }
+ x1 = g_x1;
+ }
+ if (g_y1 < y1)
+ y1 = g_y1;
+ if (g_x2 > x2)
+ x2 = g_x2;
+ if (g_y2 > y2)
+ y2 = g_y2;
+ }
+ else
+ {
+ x1 = g_x1;
+ y1 = g_y1;
+ x2 = g_x2;
+ y2 = g_y2;
+ }
+ }
+
+ if (x1 == x2 || y1 == y2)
+ goto bail1;
+
+ for (i = 0; i < nglyphs; i++)
+ if (((XftFontInt *) glyphs[i].font)->info.antialias)
+ break;
+
+ if ((i != nglyphs || color->color.alpha != 0xffff) &&
+ _XftSmoothGlyphPossible (draw))
+ {
+ XImage *image;
+ unsigned int depth;
+ int width = x2 - x1, height = y2 - y1;
+
+ /*
+ * Try to get bits directly from the drawable; if that fails,
+ * use a temporary pixmap. When it does fail, assume it
+ * will probably fail for a while and keep using temporary
+ * pixmaps for a while to avoid double round trips.
+ */
+ if (draw->core.use_pixmap == 0)
+ {
+ prev_error = XSetErrorHandler (XftGetImageErrorHandler);
+ image = XGetImage (dpy, draw->drawable,
+ x1, y1,
+ width, height, AllPlanes,
+ ZPixmap);
+ XSetErrorHandler (prev_error);
+ if (!image)
+ draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
+ }
+ else
+ {
+ draw->core.use_pixmap--;
+ image = NULL;
+ }
+ if (!image && (depth = XftDrawDepth (draw)))
+ {
+ Pixmap pix;
+ GC gc;
+ XGCValues gcv;
+
+ pix = XCreatePixmap (dpy, draw->drawable,
+ width, height, depth);
+ gcv.graphics_exposures = False;
+ gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
+ XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
+ width, height, 0, 0);
+ XFreeGC (dpy, gc);
+ image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
+ ZPixmap);
+ XFreePixmap (dpy, pix);
+ }
+ if (!image)
+ goto bail1;
+ image->red_mask = draw->visual->red_mask;
+ image->green_mask = draw->visual->green_mask;
+ image->blue_mask = draw->visual->blue_mask;
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ for (i = 0; i < nglyphs; i++)
+ {
+ XftFont *public = glyphs[i].font;
+ XftFontInt *font = (XftFontInt *) public;
+ XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
+ FT_UInt glyph = glyphs[i].glyph;
+
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ {
+ (*smooth) (image, xftg, glyphs[i].x - x1,
+ glyphs[i].y - y1, color);
+ }
+ }
+ if (image->byte_order != XftNativeByteOrder ())
+ XftSwapImage (image);
+ XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
+ width, height);
+ XDestroyImage (image);
+ }
+ else
+ {
+ for (i = 0; i < nglyphs; i++)
+ {
+ XftFont *public = glyphs[i].font;
+ XftFontInt *font = (XftFontInt *) public;
+ XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public);
+ FT_UInt glyph = glyphs[i].glyph;
+
+ if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
+ xftg = _XftGlyphDefault (dpy, public);
+ if (xftg)
+ (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
+ }
+ }
+bail1:
+ if (glyphs_loaded)
+ for (i = 0; i < nglyphs; i++)
+ _XftFontManageMemory (dpy, glyphs[i].font);
+}
diff --git a/libXft/src/xftdpy.c b/libXft/src/xftdpy.c
index 055351586..862c7e8ab 100644
--- a/libXft/src/xftdpy.c
+++ b/libXft/src/xftdpy.c
@@ -1,552 +1,552 @@
-/*
- * 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"
-
-_X_HIDDEN XftDisplayInfo *_XftDisplayInfo;
-
-static int
-_XftCloseDisplay (Display *dpy, XExtCodes *codes)
-{
- XftDisplayInfo *info, **prev;
-
- info = _XftDisplayInfoGet (dpy, FcFalse);
- if (!info)
- return 0;
-
- /*
- * Get rid of any dangling unreferenced fonts
- */
- info->max_unref_fonts = 0;
- XftFontManageMemory (dpy);
-
- /*
- * Clean up the default values
- */
- if (info->defaults)
- FcPatternDestroy (info->defaults);
-
- /*
- * Unhook from the global list
- */
- for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
- if (info->display == dpy)
- break;
- *prev = info->next;
-
- free (info);
- return 0;
-}
-
-
-_X_HIDDEN XftDisplayInfo *
-_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary)
-{
- XftDisplayInfo *info, **prev;
- XRenderPictFormat pf;
- int i;
- int event_base, error_base;
-
- for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
- {
- if (info->display == dpy)
- {
- /*
- * MRU the list
- */
- if (prev != &_XftDisplayInfo)
- {
- *prev = info->next;
- info->next = _XftDisplayInfo;
- _XftDisplayInfo = info;
- }
- return info;
- }
- }
- if (!createIfNecessary)
- return NULL;
-
- info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo));
- if (!info)
- goto bail0;
- info->codes = XAddExtension (dpy);
- if (!info->codes)
- goto bail1;
- (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay);
-
- info->display = dpy;
- info->defaults = NULL;
- info->solidFormat = NULL;
- info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
- (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL));
- info->use_free_glyphs = FcTrue;
- if (info->hasRender)
- {
- int major, minor;
- XRenderQueryVersion (dpy, &major, &minor);
- if (major < 0 || (major == 0 && minor <= 2))
- info->use_free_glyphs = FcFalse;
-
- pf.type = PictTypeDirect;
- pf.depth = 32;
- pf.direct.redMask = 0xff;
- pf.direct.greenMask = 0xff;
- pf.direct.blueMask = 0xff;
- pf.direct.alphaMask = 0xff;
- info->solidFormat = XRenderFindFormat (dpy,
- (PictFormatType|
- PictFormatDepth|
- PictFormatRedMask|
- PictFormatGreenMask|
- PictFormatBlueMask|
- PictFormatAlphaMask),
- &pf,
- 0);
- }
- if (XftDebug () & XFT_DBG_RENDER)
- {
- Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
- XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
-
- printf ("XftDisplayInfoGet Default visual 0x%x ",
- (int) visual->visualid);
- if (format)
- {
- if (format->type == PictTypeDirect)
- {
- printf ("format %d,%d,%d,%d\n",
- format->direct.alpha,
- format->direct.red,
- format->direct.green,
- format->direct.blue);
- }
- else
- {
- printf ("format indexed\n");
- }
- }
- else
- printf ("No Render format for default visual\n");
-
- printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n",
- info->hasRender ? "True" : "False");
- }
- for (i = 0; i < XFT_NUM_SOLID_COLOR; i++)
- {
- info->colors[i].screen = -1;
- info->colors[i].pict = 0;
- }
- info->fonts = NULL;
-
- info->next = _XftDisplayInfo;
- _XftDisplayInfo = info;
-
- info->glyph_memory = NULL;
- info->max_glyph_memory = XftDefaultGetInteger (dpy,
- XFT_MAX_GLYPH_MEMORY, 0,
- XFT_DPY_MAX_GLYPH_MEMORY);
- if (XftDebug () & XFT_DBG_CACHE)
- printf ("global max cache memory %ld\n", info->max_glyph_memory);
-
-
- info->num_unref_fonts = 0;
- info->max_unref_fonts = XftDefaultGetInteger (dpy,
- XFT_MAX_UNREF_FONTS, 0,
- XFT_DPY_MAX_UNREF_FONTS);
- if (XftDebug() & XFT_DBG_CACHE)
- printf ("global max unref fonts %d\n", info->max_unref_fonts);
-
- memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH);
- return info;
-
-bail1:
- free (info);
-bail0:
- if (XftDebug () & XFT_DBG_RENDER)
- {
- printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n");
- }
- return NULL;
-}
-
-/*
- * Reduce memory usage in X server
- */
-
-static void
-_XftDisplayValidateMemory (XftDisplayInfo *info)
-{
- XftFont *public;
- XftFontInt *font;
- unsigned long glyph_memory;
-
- glyph_memory = 0;
- for (public = info->fonts; public; public = font->next)
- {
- font = (XftFontInt *) public;
- glyph_memory += font->glyph_memory;
- }
- if (glyph_memory != info->glyph_memory)
- printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n",
- info->glyph_memory, glyph_memory);
-}
-
-_X_HIDDEN void
-_XftDisplayManageMemory (Display *dpy)
-{
- XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False);
- unsigned long glyph_memory;
- XftFont *public;
- XftFontInt *font;
-
- if (!info || !info->max_glyph_memory)
- return;
- if (XftDebug () & XFT_DBG_CACHE)
- {
- if (info->glyph_memory > info->max_glyph_memory)
- printf ("Reduce global memory from %ld to %ld\n",
- info->glyph_memory, info->max_glyph_memory);
- _XftDisplayValidateMemory (info);
- }
- while (info->glyph_memory > info->max_glyph_memory)
- {
- glyph_memory = rand () % info->glyph_memory;
- public = info->fonts;
- while (public)
- {
- font = (XftFontInt *) public;
-
- if (font->glyph_memory > glyph_memory)
- {
- _XftFontUncacheGlyph (dpy, public);
- break;
- }
- public = font->next;
- glyph_memory -= font->glyph_memory;
- }
- }
- if (XftDebug () & XFT_DBG_CACHE)
- _XftDisplayValidateMemory (info);
-}
-
-_X_EXPORT Bool
-XftDefaultHasRender (Display *dpy)
-{
- XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
-
- if (!info)
- return False;
- return info->hasRender;
-}
-
-_X_EXPORT Bool
-XftDefaultSet (Display *dpy, FcPattern *defaults)
-{
- XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
-
- if (!info)
- return False;
- if (info->defaults)
- FcPatternDestroy (info->defaults);
- info->defaults = defaults;
- if (!info->max_glyph_memory)
- info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY;
- info->max_glyph_memory = XftDefaultGetInteger (dpy,
- XFT_MAX_GLYPH_MEMORY, 0,
- info->max_glyph_memory);
- if (!info->max_unref_fonts)
- info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS;
- info->max_unref_fonts = XftDefaultGetInteger (dpy,
- XFT_MAX_UNREF_FONTS, 0,
- info->max_unref_fonts);
- return True;
-}
-
-_X_HIDDEN int
-XftDefaultParseBool (char *v)
-{
- char c0, c1;
-
- c0 = *v;
- if (isupper ((int)c0))
- c0 = tolower (c0);
- if (c0 == 't' || c0 == 'y' || c0 == '1')
- return 1;
- if (c0 == 'f' || c0 == 'n' || c0 == '0')
- return 0;
- if (c0 == 'o')
- {
- c1 = v[1];
- if (isupper ((int)c1))
- c1 = tolower (c1);
- if (c1 == 'n')
- return 1;
- if (c1 == 'f')
- return 0;
- }
- return -1;
-}
-
-static Bool
-_XftDefaultInitBool (Display *dpy, FcPattern *pat, char *option)
-{
- char *v;
- int i;
-
- v = XGetDefault (dpy, "Xft", option);
- if (v && (i = XftDefaultParseBool (v)) >= 0)
- return FcPatternAddBool (pat, option, i != 0);
- return True;
-}
-
-static Bool
-_XftDefaultInitDouble (Display *dpy, FcPattern *pat, char *option)
-{
- char *v, *e;
- double d;
-
- v = XGetDefault (dpy, "Xft", option);
- if (v)
- {
- d = strtod (v, &e);
- if (e != v)
- return FcPatternAddDouble (pat, option, d);
- }
- return True;
-}
-
-static Bool
-_XftDefaultInitInteger (Display *dpy, FcPattern *pat, char *option)
-{
- char *v, *e;
- int i;
-
- v = XGetDefault (dpy, "Xft", option);
- if (v)
- {
- if (FcNameConstant ((FcChar8 *) v, &i))
- return FcPatternAddInteger (pat, option, i);
- i = strtol (v, &e, 0);
- if (e != v)
- return FcPatternAddInteger (pat, option, i);
- }
- return True;
-}
-
-static FcPattern *
-_XftDefaultInit (Display *dpy)
-{
- FcPattern *pat;
-
- pat = FcPatternCreate ();
- if (!pat)
- goto bail0;
-
- if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE))
- goto bail1;
- if (!_XftDefaultInitDouble (dpy, pat, FC_DPI))
- goto bail1;
- if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER))
- goto bail1;
- if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA))
- goto bail1;
- if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS))
- goto bail1;
-#ifdef FC_EMBOLDEN
- if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN))
- goto bail1;
-#endif
- if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT))
- goto bail1;
-#ifdef FC_HINT_STYLE
- if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE))
- goto bail1;
-#endif
- if (!_XftDefaultInitBool (dpy, pat, FC_HINTING))
- goto bail1;
- if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE))
- goto bail1;
- if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY))
- goto bail1;
-
- return pat;
-
-bail1:
- FcPatternDestroy (pat);
-bail0:
- return NULL;
-}
-
-static FcResult
-_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v)
-{
- XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
- FcResult r;
-
- if (!info)
- return FcResultNoMatch;
-
- if (!info->defaults)
- {
- info->defaults = _XftDefaultInit (dpy);
- if (!info->defaults)
- return FcResultNoMatch;
- }
- r = FcPatternGet (info->defaults, object, screen, v);
- if (r == FcResultNoId && screen > 0)
- r = FcPatternGet (info->defaults, object, 0, v);
- return r;
-}
-
-_X_HIDDEN Bool
-XftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def)
-{
- FcResult r;
- FcValue v;
-
- r = _XftDefaultGet (dpy, object, screen, &v);
- if (r != FcResultMatch || v.type != FcTypeBool)
- return def;
- return v.u.b;
-}
-
-_X_HIDDEN int
-XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def)
-{
- FcResult r;
- FcValue v;
-
- r = _XftDefaultGet (dpy, object, screen, &v);
- if (r != FcResultMatch || v.type != FcTypeInteger)
- return def;
- return v.u.i;
-}
-
-_X_HIDDEN double
-XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def)
-{
- FcResult r;
- FcValue v;
-
- r = _XftDefaultGet (dpy, object, screen, &v);
- if (r != FcResultMatch || v.type != FcTypeDouble)
- return def;
- return v.u.d;
-}
-
-_X_EXPORT void
-XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern)
-{
- FcValue v;
- double dpi;
-
- if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, XFT_RENDER,
- XftDefaultGetBool (dpy, XFT_RENDER, screen,
- XftDefaultHasRender (dpy)));
- }
- if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_ANTIALIAS,
- XftDefaultGetBool (dpy, FC_ANTIALIAS, screen,
- True));
- }
-#ifdef FC_EMBOLDEN
- if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_EMBOLDEN,
- XftDefaultGetBool (dpy, FC_EMBOLDEN, screen,
- False));
- }
-#endif
- if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_HINTING,
- XftDefaultGetBool (dpy, FC_HINTING, screen,
- True));
- }
-#ifdef FC_HINT_STYLE
- if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddInteger (pattern, FC_HINT_STYLE,
- XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen,
- FC_HINT_FULL));
- }
-#endif
- if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_AUTOHINT,
- XftDefaultGetBool (dpy, FC_AUTOHINT, screen,
- False));
- }
- if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
- {
- int subpixel = FC_RGBA_UNKNOWN;
-#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
- if (XftDefaultHasRender (dpy))
- {
- int render_order = XRenderQuerySubpixelOrder (dpy, screen);
- switch (render_order) {
- default:
- case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break;
- case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break;
- case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break;
- case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break;
- case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break;
- case SubPixelNone: subpixel = FC_RGBA_NONE; break;
- }
- }
-#endif
- FcPatternAddInteger (pattern, FC_RGBA,
- XftDefaultGetInteger (dpy, FC_RGBA, screen,
- subpixel));
- }
- if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_MINSPACE,
- XftDefaultGetBool (dpy, FC_MINSPACE, screen,
- False));
- }
- if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
- {
- dpi = (((double) DisplayHeight (dpy, screen) * 25.4) /
- (double) DisplayHeightMM (dpy, screen));
- FcPatternAddDouble (pattern, FC_DPI,
- XftDefaultGetDouble (dpy, FC_DPI, screen,
- dpi));
- }
- if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddDouble (pattern, FC_SCALE,
- XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0));
- }
- if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY,
- XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY,
- screen,
- XFT_FONT_MAX_GLYPH_MEMORY));
- }
- FcDefaultSubstitute (pattern);
-}
-
+/*
+ * 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"
+
+_X_HIDDEN XftDisplayInfo *_XftDisplayInfo;
+
+static int
+_XftCloseDisplay (Display *dpy, XExtCodes *codes)
+{
+ XftDisplayInfo *info, **prev;
+
+ info = _XftDisplayInfoGet (dpy, FcFalse);
+ if (!info)
+ return 0;
+
+ /*
+ * Get rid of any dangling unreferenced fonts
+ */
+ info->max_unref_fonts = 0;
+ XftFontManageMemory (dpy);
+
+ /*
+ * Clean up the default values
+ */
+ if (info->defaults)
+ FcPatternDestroy (info->defaults);
+
+ /*
+ * Unhook from the global list
+ */
+ for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ if (info->display == dpy)
+ break;
+ *prev = info->next;
+
+ free (info);
+ return 0;
+}
+
+
+_X_HIDDEN XftDisplayInfo *
+_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary)
+{
+ XftDisplayInfo *info, **prev;
+ XRenderPictFormat pf;
+ int i;
+ int event_base, error_base;
+
+ for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ {
+ if (info->display == dpy)
+ {
+ /*
+ * MRU the list
+ */
+ if (prev != &_XftDisplayInfo)
+ {
+ *prev = info->next;
+ info->next = _XftDisplayInfo;
+ _XftDisplayInfo = info;
+ }
+ return info;
+ }
+ }
+ if (!createIfNecessary)
+ return NULL;
+
+ info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo));
+ if (!info)
+ goto bail0;
+ info->codes = XAddExtension (dpy);
+ if (!info->codes)
+ goto bail1;
+ (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay);
+
+ info->display = dpy;
+ info->defaults = NULL;
+ info->solidFormat = NULL;
+ info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
+ (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL));
+ info->use_free_glyphs = FcTrue;
+ if (info->hasRender)
+ {
+ int major, minor;
+ XRenderQueryVersion (dpy, &major, &minor);
+ if (major < 0 || (major == 0 && minor <= 2))
+ info->use_free_glyphs = FcFalse;
+
+ pf.type = PictTypeDirect;
+ pf.depth = 32;
+ pf.direct.redMask = 0xff;
+ pf.direct.greenMask = 0xff;
+ pf.direct.blueMask = 0xff;
+ pf.direct.alphaMask = 0xff;
+ info->solidFormat = XRenderFindFormat (dpy,
+ (PictFormatType|
+ PictFormatDepth|
+ PictFormatRedMask|
+ PictFormatGreenMask|
+ PictFormatBlueMask|
+ PictFormatAlphaMask),
+ &pf,
+ 0);
+ }
+ if (XftDebug () & XFT_DBG_RENDER)
+ {
+ Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
+ XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
+
+ printf ("XftDisplayInfoGet Default visual 0x%x ",
+ (int) visual->visualid);
+ if (format)
+ {
+ if (format->type == PictTypeDirect)
+ {
+ printf ("format %d,%d,%d,%d\n",
+ format->direct.alpha,
+ format->direct.red,
+ format->direct.green,
+ format->direct.blue);
+ }
+ else
+ {
+ printf ("format indexed\n");
+ }
+ }
+ else
+ printf ("No Render format for default visual\n");
+
+ printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n",
+ info->hasRender ? "True" : "False");
+ }
+ for (i = 0; i < XFT_NUM_SOLID_COLOR; i++)
+ {
+ info->colors[i].screen = -1;
+ info->colors[i].pict = 0;
+ }
+ info->fonts = NULL;
+
+ info->next = _XftDisplayInfo;
+ _XftDisplayInfo = info;
+
+ info->glyph_memory = 0;
+ info->max_glyph_memory = XftDefaultGetInteger (dpy,
+ XFT_MAX_GLYPH_MEMORY, 0,
+ XFT_DPY_MAX_GLYPH_MEMORY);
+ if (XftDebug () & XFT_DBG_CACHE)
+ printf ("global max cache memory %ld\n", info->max_glyph_memory);
+
+
+ info->num_unref_fonts = 0;
+ info->max_unref_fonts = XftDefaultGetInteger (dpy,
+ XFT_MAX_UNREF_FONTS, 0,
+ XFT_DPY_MAX_UNREF_FONTS);
+ if (XftDebug() & XFT_DBG_CACHE)
+ printf ("global max unref fonts %d\n", info->max_unref_fonts);
+
+ memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH);
+ return info;
+
+bail1:
+ free (info);
+bail0:
+ if (XftDebug () & XFT_DBG_RENDER)
+ {
+ printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n");
+ }
+ return NULL;
+}
+
+/*
+ * Reduce memory usage in X server
+ */
+
+static void
+_XftDisplayValidateMemory (XftDisplayInfo *info)
+{
+ XftFont *public;
+ XftFontInt *font;
+ unsigned long glyph_memory;
+
+ glyph_memory = 0;
+ for (public = info->fonts; public; public = font->next)
+ {
+ font = (XftFontInt *) public;
+ glyph_memory += font->glyph_memory;
+ }
+ if (glyph_memory != info->glyph_memory)
+ printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n",
+ info->glyph_memory, glyph_memory);
+}
+
+_X_HIDDEN void
+_XftDisplayManageMemory (Display *dpy)
+{
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False);
+ unsigned long glyph_memory;
+ XftFont *public;
+ XftFontInt *font;
+
+ if (!info || !info->max_glyph_memory)
+ return;
+ if (XftDebug () & XFT_DBG_CACHE)
+ {
+ if (info->glyph_memory > info->max_glyph_memory)
+ printf ("Reduce global memory from %ld to %ld\n",
+ info->glyph_memory, info->max_glyph_memory);
+ _XftDisplayValidateMemory (info);
+ }
+ while (info->glyph_memory > info->max_glyph_memory)
+ {
+ glyph_memory = rand () % info->glyph_memory;
+ public = info->fonts;
+ while (public)
+ {
+ font = (XftFontInt *) public;
+
+ if (font->glyph_memory > glyph_memory)
+ {
+ _XftFontUncacheGlyph (dpy, public);
+ break;
+ }
+ public = font->next;
+ glyph_memory -= font->glyph_memory;
+ }
+ }
+ if (XftDebug () & XFT_DBG_CACHE)
+ _XftDisplayValidateMemory (info);
+}
+
+_X_EXPORT Bool
+XftDefaultHasRender (Display *dpy)
+{
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
+
+ if (!info)
+ return False;
+ return info->hasRender;
+}
+
+_X_EXPORT Bool
+XftDefaultSet (Display *dpy, FcPattern *defaults)
+{
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
+
+ if (!info)
+ return False;
+ if (info->defaults)
+ FcPatternDestroy (info->defaults);
+ info->defaults = defaults;
+ if (!info->max_glyph_memory)
+ info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY;
+ info->max_glyph_memory = XftDefaultGetInteger (dpy,
+ XFT_MAX_GLYPH_MEMORY, 0,
+ info->max_glyph_memory);
+ if (!info->max_unref_fonts)
+ info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS;
+ info->max_unref_fonts = XftDefaultGetInteger (dpy,
+ XFT_MAX_UNREF_FONTS, 0,
+ info->max_unref_fonts);
+ return True;
+}
+
+_X_HIDDEN int
+XftDefaultParseBool (char *v)
+{
+ char c0, c1;
+
+ c0 = *v;
+ if (isupper ((int)c0))
+ c0 = tolower (c0);
+ if (c0 == 't' || c0 == 'y' || c0 == '1')
+ return 1;
+ if (c0 == 'f' || c0 == 'n' || c0 == '0')
+ return 0;
+ if (c0 == 'o')
+ {
+ c1 = v[1];
+ if (isupper ((int)c1))
+ c1 = tolower (c1);
+ if (c1 == 'n')
+ return 1;
+ if (c1 == 'f')
+ return 0;
+ }
+ return -1;
+}
+
+static Bool
+_XftDefaultInitBool (Display *dpy, FcPattern *pat, char *option)
+{
+ char *v;
+ int i;
+
+ v = XGetDefault (dpy, "Xft", option);
+ if (v && (i = XftDefaultParseBool (v)) >= 0)
+ return FcPatternAddBool (pat, option, i != 0);
+ return True;
+}
+
+static Bool
+_XftDefaultInitDouble (Display *dpy, FcPattern *pat, char *option)
+{
+ char *v, *e;
+ double d;
+
+ v = XGetDefault (dpy, "Xft", option);
+ if (v)
+ {
+ d = strtod (v, &e);
+ if (e != v)
+ return FcPatternAddDouble (pat, option, d);
+ }
+ return True;
+}
+
+static Bool
+_XftDefaultInitInteger (Display *dpy, FcPattern *pat, char *option)
+{
+ char *v, *e;
+ int i;
+
+ v = XGetDefault (dpy, "Xft", option);
+ if (v)
+ {
+ if (FcNameConstant ((FcChar8 *) v, &i))
+ return FcPatternAddInteger (pat, option, i);
+ i = strtol (v, &e, 0);
+ if (e != v)
+ return FcPatternAddInteger (pat, option, i);
+ }
+ return True;
+}
+
+static FcPattern *
+_XftDefaultInit (Display *dpy)
+{
+ FcPattern *pat;
+
+ pat = FcPatternCreate ();
+ if (!pat)
+ goto bail0;
+
+ if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE))
+ goto bail1;
+ if (!_XftDefaultInitDouble (dpy, pat, FC_DPI))
+ goto bail1;
+ if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER))
+ goto bail1;
+ if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA))
+ goto bail1;
+ if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS))
+ goto bail1;
+#ifdef FC_EMBOLDEN
+ if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN))
+ goto bail1;
+#endif
+ if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT))
+ goto bail1;
+#ifdef FC_HINT_STYLE
+ if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE))
+ goto bail1;
+#endif
+ if (!_XftDefaultInitBool (dpy, pat, FC_HINTING))
+ goto bail1;
+ if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE))
+ goto bail1;
+ if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY))
+ goto bail1;
+
+ return pat;
+
+bail1:
+ FcPatternDestroy (pat);
+bail0:
+ return NULL;
+}
+
+static FcResult
+_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v)
+{
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
+ FcResult r;
+
+ if (!info)
+ return FcResultNoMatch;
+
+ if (!info->defaults)
+ {
+ info->defaults = _XftDefaultInit (dpy);
+ if (!info->defaults)
+ return FcResultNoMatch;
+ }
+ r = FcPatternGet (info->defaults, object, screen, v);
+ if (r == FcResultNoId && screen > 0)
+ r = FcPatternGet (info->defaults, object, 0, v);
+ return r;
+}
+
+_X_HIDDEN Bool
+XftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def)
+{
+ FcResult r;
+ FcValue v;
+
+ r = _XftDefaultGet (dpy, object, screen, &v);
+ if (r != FcResultMatch || v.type != FcTypeBool)
+ return def;
+ return v.u.b;
+}
+
+_X_HIDDEN int
+XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def)
+{
+ FcResult r;
+ FcValue v;
+
+ r = _XftDefaultGet (dpy, object, screen, &v);
+ if (r != FcResultMatch || v.type != FcTypeInteger)
+ return def;
+ return v.u.i;
+}
+
+_X_HIDDEN double
+XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def)
+{
+ FcResult r;
+ FcValue v;
+
+ r = _XftDefaultGet (dpy, object, screen, &v);
+ if (r != FcResultMatch || v.type != FcTypeDouble)
+ return def;
+ return v.u.d;
+}
+
+_X_EXPORT void
+XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern)
+{
+ FcValue v;
+ double dpi;
+
+ if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, XFT_RENDER,
+ XftDefaultGetBool (dpy, XFT_RENDER, screen,
+ XftDefaultHasRender (dpy)));
+ }
+ if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_ANTIALIAS,
+ XftDefaultGetBool (dpy, FC_ANTIALIAS, screen,
+ True));
+ }
+#ifdef FC_EMBOLDEN
+ if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_EMBOLDEN,
+ XftDefaultGetBool (dpy, FC_EMBOLDEN, screen,
+ False));
+ }
+#endif
+ if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_HINTING,
+ XftDefaultGetBool (dpy, FC_HINTING, screen,
+ True));
+ }
+#ifdef FC_HINT_STYLE
+ if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddInteger (pattern, FC_HINT_STYLE,
+ XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen,
+ FC_HINT_FULL));
+ }
+#endif
+ if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_AUTOHINT,
+ XftDefaultGetBool (dpy, FC_AUTOHINT, screen,
+ False));
+ }
+ if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
+ {
+ int subpixel = FC_RGBA_UNKNOWN;
+#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
+ if (XftDefaultHasRender (dpy))
+ {
+ int render_order = XRenderQuerySubpixelOrder (dpy, screen);
+ switch (render_order) {
+ default:
+ case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break;
+ case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break;
+ case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break;
+ case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break;
+ case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break;
+ case SubPixelNone: subpixel = FC_RGBA_NONE; break;
+ }
+ }
+#endif
+ FcPatternAddInteger (pattern, FC_RGBA,
+ XftDefaultGetInteger (dpy, FC_RGBA, screen,
+ subpixel));
+ }
+ if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_MINSPACE,
+ XftDefaultGetBool (dpy, FC_MINSPACE, screen,
+ False));
+ }
+ if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
+ {
+ dpi = (((double) DisplayHeight (dpy, screen) * 25.4) /
+ (double) DisplayHeightMM (dpy, screen));
+ FcPatternAddDouble (pattern, FC_DPI,
+ XftDefaultGetDouble (dpy, FC_DPI, screen,
+ dpi));
+ }
+ if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddDouble (pattern, FC_SCALE,
+ XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0));
+ }
+ if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY,
+ XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY,
+ screen,
+ XFT_FONT_MAX_GLYPH_MEMORY));
+ }
+ FcDefaultSubstitute (pattern);
+}
+
diff --git a/libXft/src/xftdraw.c b/libXft/src/xftdraw.c
index ab5174973..7b8f84dd5 100644
--- a/libXft/src/xftdraw.c
+++ b/libXft/src/xftdraw.c
@@ -1,994 +1,994 @@
-/*
- * 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;
-}
-
-_X_HIDDEN 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;
-}
-
-_X_HIDDEN 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;
-}
-
-_X_EXPORT XftDraw *
-XftDrawCreate (Display *dpy,
- Drawable drawable,
- Visual *visual,
- Colormap colormap)
-{
- XftDraw *draw;
-
- draw = (XftDraw *) malloc (sizeof (XftDraw));
- if (!draw)
- return NULL;
-
- 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 = NULL;
- draw->core.use_pixmap = 0;
- draw->clip_type = XftClipTypeNone;
- draw->subwindow_mode = ClipByChildren;
- XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
- return draw;
-}
-
-_X_EXPORT XftDraw *
-XftDrawCreateBitmap (Display *dpy,
- Pixmap bitmap)
-{
- XftDraw *draw;
-
- draw = (XftDraw *) malloc (sizeof (XftDraw));
- if (!draw)
- return NULL;
- draw->dpy = dpy;
- draw->drawable = (Drawable) bitmap;
- draw->screen = _XftDrawScreen (dpy, bitmap, NULL);
- draw->depth = 1;
- draw->bits_per_pixel = 1;
- draw->visual = NULL;
- draw->colormap = 0;
- draw->render.pict = 0;
- draw->core.gc = NULL;
- draw->core.use_pixmap = 0;
- draw->clip_type = XftClipTypeNone;
- draw->subwindow_mode = ClipByChildren;
- XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
- return draw;
-}
-
-_X_EXPORT XftDraw *
-XftDrawCreateAlpha (Display *dpy,
- Pixmap pixmap,
- int depth)
-{
- XftDraw *draw;
-
- draw = (XftDraw *) malloc (sizeof (XftDraw));
- if (!draw)
- return NULL;
- draw->dpy = dpy;
- draw->drawable = (Drawable) pixmap;
- draw->screen = _XftDrawScreen (dpy, pixmap, NULL);
- draw->depth = depth;
- draw->bits_per_pixel = 0; /* don't find out until we need it */
- draw->visual = NULL;
- draw->colormap = 0;
- draw->render.pict = 0;
- draw->core.gc = NULL;
- 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 || !info->hasRender)
- return NULL;
-
- if (draw->visual == NULL)
- {
- 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);
-}
-
-_X_EXPORT 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 = NULL;
- }
-}
-
-_X_EXPORT Display *
-XftDrawDisplay (XftDraw *draw)
-{
- return draw->dpy;
-}
-
-_X_EXPORT Drawable
-XftDrawDrawable (XftDraw *draw)
-{
- return draw->drawable;
-}
-
-_X_EXPORT Colormap
-XftDrawColormap (XftDraw *draw)
-{
- return draw->colormap;
-}
-
-_X_EXPORT Visual *
-XftDrawVisual (XftDraw *draw)
-{
- return draw->visual;
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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;
-}
-
-_X_EXPORT Picture
-XftDrawPicture (XftDraw *draw)
-{
- if (!_XftDrawRenderPrepare (draw))
- return 0;
- return draw->render.pict;
-}
-
-#define NUM_LOCAL 1024
-
-_X_EXPORT 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);
- }
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
- }
-}
-
-_X_EXPORT 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);
- }
- }
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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);
-}
-
-_X_EXPORT 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))
- {
- /* note: not XftRectCore() */
- XSetForeground (draw->dpy, draw->core.gc, color->pixel);
- XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
- x, y, width, height);
- }
-}
-
-_X_EXPORT Bool
-XftDrawSetClip (XftDraw *draw,
- Region r)
-{
- Region n = NULL;
-
- /*
- * 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;
-}
-
-_X_EXPORT Bool
-XftDrawSetClipRectangles (XftDraw *draw,
- int xOrigin,
- int yOrigin,
- _Xconst XRectangle *rects,
- int n)
-{
- XftClipRect *new = NULL;
-
- /*
- * 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;
-}
-
-_X_EXPORT 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);
-}
+/*
+ * 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;
+}
+
+_X_HIDDEN 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;
+}
+
+_X_HIDDEN 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;
+}
+
+_X_EXPORT XftDraw *
+XftDrawCreate (Display *dpy,
+ Drawable drawable,
+ Visual *visual,
+ Colormap colormap)
+{
+ XftDraw *draw;
+
+ draw = (XftDraw *) malloc (sizeof (XftDraw));
+ if (!draw)
+ return NULL;
+
+ 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 = NULL;
+ draw->core.use_pixmap = 0;
+ draw->clip_type = XftClipTypeNone;
+ draw->subwindow_mode = ClipByChildren;
+ XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
+ return draw;
+}
+
+_X_EXPORT XftDraw *
+XftDrawCreateBitmap (Display *dpy,
+ Pixmap bitmap)
+{
+ XftDraw *draw;
+
+ draw = (XftDraw *) malloc (sizeof (XftDraw));
+ if (!draw)
+ return NULL;
+ draw->dpy = dpy;
+ draw->drawable = (Drawable) bitmap;
+ draw->screen = _XftDrawScreen (dpy, bitmap, NULL);
+ draw->depth = 1;
+ draw->bits_per_pixel = 1;
+ draw->visual = NULL;
+ draw->colormap = 0;
+ draw->render.pict = 0;
+ draw->core.gc = NULL;
+ draw->core.use_pixmap = 0;
+ draw->clip_type = XftClipTypeNone;
+ draw->subwindow_mode = ClipByChildren;
+ XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
+ return draw;
+}
+
+_X_EXPORT XftDraw *
+XftDrawCreateAlpha (Display *dpy,
+ Pixmap pixmap,
+ int depth)
+{
+ XftDraw *draw;
+
+ draw = (XftDraw *) malloc (sizeof (XftDraw));
+ if (!draw)
+ return NULL;
+ draw->dpy = dpy;
+ draw->drawable = (Drawable) pixmap;
+ draw->screen = _XftDrawScreen (dpy, pixmap, NULL);
+ draw->depth = depth;
+ draw->bits_per_pixel = 0; /* don't find out until we need it */
+ draw->visual = NULL;
+ draw->colormap = 0;
+ draw->render.pict = 0;
+ draw->core.gc = NULL;
+ 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 || !info->hasRender)
+ return NULL;
+
+ if (draw->visual == NULL)
+ {
+ 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);
+}
+
+_X_EXPORT 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 = NULL;
+ }
+}
+
+_X_EXPORT Display *
+XftDrawDisplay (XftDraw *draw)
+{
+ return draw->dpy;
+}
+
+_X_EXPORT Drawable
+XftDrawDrawable (XftDraw *draw)
+{
+ return draw->drawable;
+}
+
+_X_EXPORT Colormap
+XftDrawColormap (XftDraw *draw)
+{
+ return draw->colormap;
+}
+
+_X_EXPORT Visual *
+XftDrawVisual (XftDraw *draw)
+{
+ return draw->visual;
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT Picture
+XftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color)
+{
+ Display *dpy = draw->dpy;
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
+ int i;
+ XftColor bitmapColor;
+
+ if (!info || !info->solidFormat)
+ 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;
+}
+
+_X_EXPORT Picture
+XftDrawPicture (XftDraw *draw)
+{
+ if (!_XftDrawRenderPrepare (draw))
+ return 0;
+ return draw->render.pict;
+}
+
+#define NUM_LOCAL 1024
+
+_X_EXPORT 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);
+ }
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+ }
+}
+
+_X_EXPORT 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);
+ }
+ }
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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);
+}
+
+_X_EXPORT 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))
+ {
+ /* note: not XftRectCore() */
+ XSetForeground (draw->dpy, draw->core.gc, color->pixel);
+ XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
+ x, y, width, height);
+ }
+}
+
+_X_EXPORT Bool
+XftDrawSetClip (XftDraw *draw,
+ Region r)
+{
+ Region n = NULL;
+
+ /*
+ * 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;
+}
+
+_X_EXPORT Bool
+XftDrawSetClipRectangles (XftDraw *draw,
+ int xOrigin,
+ int yOrigin,
+ _Xconst XRectangle *rects,
+ int n)
+{
+ XftClipRect *new = NULL;
+
+ /*
+ * 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;
+}
+
+_X_EXPORT 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);
+}