summaryrefslogtreecommitdiff
path: root/src/xftcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xftcore.c')
-rw-r--r--src/xftcore.c1377
1 files changed, 1377 insertions, 0 deletions
diff --git a/src/xftcore.c b/src/xftcore.c
new file mode 100644
index 0000000..5c0009d
--- /dev/null
+++ b/src/xftcore.c
@@ -0,0 +1,1377 @@
+/*
+ * $XFree86: xc/lib/Xft/xftcore.c,v 1.13 2003/02/15 22:30:51 dawes Exp $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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 <stdlib.h>
+#include "xftint.h"
+#include <X11/Xmd.h>
+
+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, FcTrue, missing, nmissing);
+ return font->glyphs[0];
+}
+
+static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event)
+{
+ return 0;
+}
+
+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 = 0;
+ }
+ 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
+
+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 = 0;
+ }
+ 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);
+}
+
+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 = 0;
+ }
+ 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);
+}