diff options
Diffstat (limited to 'libXft/src/xftcore.c')
-rw-r--r-- | libXft/src/xftcore.c | 1373 |
1 files changed, 1373 insertions, 0 deletions
diff --git a/libXft/src/xftcore.c b/libXft/src/xftcore.c new file mode 100644 index 000000000..3f8710929 --- /dev/null +++ b/libXft/src/xftcore.c @@ -0,0 +1,1373 @@ +/* + * 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); +} |