Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright  2000 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #include "xftint.h"
     24 
     25 _X_HIDDEN void
     26 XftRectCore (XftDraw		*draw,
     27 	     _Xconst XftColor	*color,
     28 	     int		x,
     29 	     int		y,
     30 	     unsigned int	width,
     31 	     unsigned int	height)
     32 {
     33     if (color->color.alpha >= 0x8000)
     34     {
     35 	XSetForeground (draw->dpy, draw->core.gc, color->pixel);
     36 	XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
     37 			x, y, width, height);
     38     }
     39 }
     40 
     41 /*
     42  * Use the core protocol to draw the glyphs
     43  */
     44 
     45 static void
     46 _XftSharpGlyphMono (XftDraw	*draw,
     47 		    XftGlyph	*glyph,
     48 		    int		x,
     49 		    int		y)
     50 {
     51     unsigned char   *srcLine = glyph->bitmap, *src;
     52     unsigned char   bits, bitsMask;
     53     int		    width = glyph->metrics.width;
     54     int		    stride = ((width + 31) & ~31) >> 3;
     55     int		    height = glyph->metrics.height;
     56     int		    w;
     57     int		    xspan, lenspan;
     58 
     59     x -= glyph->metrics.x;
     60     y -= glyph->metrics.y;
     61     while (height--)
     62     {
     63 	src = srcLine;
     64 	srcLine += stride;
     65 	w = width;
     66 
     67 	bitsMask = 0x80;    /* FreeType is always MSB first */
     68 	bits = *src++;
     69 
     70 	xspan = x;
     71 	while (w)
     72 	{
     73 	    if (bits & bitsMask)
     74 	    {
     75 		lenspan = 0;
     76 		do
     77 		{
     78 		    lenspan++;
     79 		    if (lenspan == w)
     80 			break;
     81 		    bitsMask = bitsMask >> 1;
     82 		    if (!bitsMask)
     83 		    {
     84 			bits = *src++;
     85 			bitsMask = 0x80;
     86 		    }
     87 		} while (bits & bitsMask);
     88 		XFillRectangle (draw->dpy, draw->drawable,
     89 				draw->core.gc, xspan, y, (unsigned)lenspan, 1);
     90 		xspan += lenspan;
     91 		w -= lenspan;
     92 	    }
     93 	    else
     94 	    {
     95 		do
     96 		{
     97 		    w--;
     98 		    xspan++;
     99 		    if (!w)
    100 			break;
    101 		    bitsMask = bitsMask >> 1;
    102 		    if (!bitsMask)
    103 		    {
    104 			bits = *src++;
    105 			bitsMask = 0x80;
    106 		    }
    107 		} while (!(bits & bitsMask));
    108 	    }
    109 	}
    110 	y++;
    111     }
    112 }
    113 
    114 /*
    115  * Draw solid color text from an anti-aliased bitmap.  This is a
    116  * fallback for cases where a particular drawable has no AA code
    117  */
    118 static void
    119 _XftSharpGlyphGray (XftDraw	*draw,
    120 		    XftGlyph	*glyph,
    121 		    int		x,
    122 		    int		y)
    123 {
    124     unsigned char   *srcLine = glyph->bitmap, *src, bits;
    125     int		    width = glyph->metrics.width;
    126     int		    stride = ((width + 3) & ~3);
    127     int		    height = glyph->metrics.height;
    128     int		    w;
    129     int		    xspan, lenspan;
    130 
    131     x -= glyph->metrics.x;
    132     y -= glyph->metrics.y;
    133     while (height--)
    134     {
    135 	src = srcLine;
    136 	srcLine += stride;
    137 	w = width;
    138 
    139 	bits = *src++;
    140 	xspan = x;
    141 	while (w)
    142 	{
    143 	    if (bits >= 0x80)
    144 	    {
    145 		lenspan = 0;
    146 		do
    147 		{
    148 		    lenspan++;
    149 		    if (lenspan == w)
    150 			break;
    151 		    bits = *src++;
    152 		} while (bits >= 0x80);
    153 		XFillRectangle (draw->dpy, draw->drawable,
    154 				draw->core.gc, xspan, y, (unsigned)lenspan, 1);
    155 		xspan += lenspan;
    156 		w -= lenspan;
    157 	    }
    158 	    else
    159 	    {
    160 		do
    161 		{
    162 		    w--;
    163 		    xspan++;
    164 		    if (!w)
    165 			break;
    166 		    bits = *src++;
    167 		} while (bits < 0x80);
    168 	    }
    169 	}
    170 	y++;
    171     }
    172 }
    173 
    174 static void
    175 _XftSharpGlyphRgba (XftDraw	*draw,
    176 		    XftGlyph	*glyph,
    177 		    int		x,
    178 		    int		y)
    179 {
    180     CARD32	    *srcLine = glyph->bitmap, *src, bits;
    181     int		    width = glyph->metrics.width;
    182     int		    stride = ((width + 3) & ~3);
    183     int		    height = glyph->metrics.height;
    184     int		    w;
    185     int		    xspan, lenspan;
    186 
    187     x -= glyph->metrics.x;
    188     y -= glyph->metrics.y;
    189     while (height--)
    190     {
    191 	src = srcLine;
    192 	srcLine += stride;
    193 	w = width;
    194 
    195 	bits = *src++;
    196 	xspan = x;
    197 	while (w)
    198 	{
    199 	    if (bits >= 0x80000000)
    200 	    {
    201 		lenspan = 0;
    202 		do
    203 		{
    204 		    lenspan++;
    205 		    if (lenspan == w)
    206 			break;
    207 		    bits = *src++;
    208 		} while (bits >= 0x80000000);
    209 		XFillRectangle (draw->dpy, draw->drawable,
    210 				draw->core.gc, xspan, y, (unsigned)lenspan, 1);
    211 		xspan += lenspan;
    212 		w -= lenspan;
    213 	    }
    214 	    else
    215 	    {
    216 		do
    217 		{
    218 		    w--;
    219 		    xspan++;
    220 		    if (!w)
    221 			break;
    222 		    bits = *src++;
    223 		} while (bits < 0x80000000);
    224 	    }
    225 	}
    226 	y++;
    227     }
    228 }
    229 
    230 typedef void (*XftSharpGlyph) (XftDraw	*draw,
    231 			       XftGlyph	*glyph,
    232 			       int	x,
    233 			       int	y);
    234 
    235 static XftSharpGlyph
    236 _XftSharpGlyphFind (XftDraw *draw _X_UNUSED, XftFont *public)
    237 {
    238     XftFontInt *font = (XftFontInt *) public;
    239 
    240     if (!font->info.antialias)
    241 	return _XftSharpGlyphMono;
    242     else switch (font->info.rgba) {
    243     case FC_RGBA_RGB:
    244     case FC_RGBA_BGR:
    245     case FC_RGBA_VRGB:
    246     case FC_RGBA_VBGR:
    247 	return _XftSharpGlyphRgba;
    248     default:
    249 	return _XftSharpGlyphGray;
    250     }
    251 }
    252 
    253 /*
    254  * Draw glyphs to a target that supports anti-aliasing
    255  */
    256 
    257 /*
    258  * Primitives for converting between RGB values and TrueColor pixels
    259  */
    260 
    261 static void
    262 _XftExamineBitfield (unsigned long mask, int *shift, int *len)
    263 {
    264     int	s, l;
    265 
    266     s = 0;
    267     while ((mask & 1) == 0)
    268     {
    269 	mask >>= 1;
    270 	s++;
    271     }
    272     l = 0;
    273     while ((mask & 1) == 1)
    274     {
    275 	mask >>= 1;
    276 	l++;
    277     }
    278     *shift = s;
    279     *len = l;
    280 }
    281 
    282 static CARD32
    283 _XftGetField (unsigned long l_pixel, int shift, int len)
    284 {
    285     CARD32  pixel = (CARD32) l_pixel;
    286 
    287     pixel = pixel & (CARD32)(((1 << (len)) - 1) << shift);
    288     pixel = pixel << (32 - (shift + len)) >> 24;
    289     while (len < 8)
    290     {
    291 	pixel |= (pixel >> len);
    292 	len <<= 1;
    293     }
    294     return pixel;
    295 }
    296 
    297 static unsigned long
    298 _XftPutField (CARD32 pixel, int shift, int len)
    299 {
    300     unsigned long   l_pixel = (unsigned long) pixel;
    301 
    302     shift = shift - (8 - len);
    303     if (len <= 8)
    304 	l_pixel = l_pixel & (unsigned long)(((1 << len) - 1) << (8 - len));
    305     if (shift < 0)
    306 	l_pixel >>= -shift;
    307     else
    308 	l_pixel <<= shift;
    309     return l_pixel;
    310 }
    311 
    312 /*
    313  * This is used when doing XftCharFontSpec/XftGlyphFontSpec where
    314  * some of the fonts are bitmaps and some are anti-aliased to handle
    315  * the bitmap portions
    316  */
    317 static void
    318 _XftSmoothGlyphMono (XImage		*image,
    319 		     _Xconst XftGlyph	*xftg,
    320 		     int		x,
    321 		     int		y,
    322 		     _Xconst XftColor   *color)
    323 {
    324     unsigned char   *srcLine = xftg->bitmap, *src;
    325     unsigned char   bits, bitsMask;
    326     int		    width = xftg->metrics.width;
    327     int		    stride = ((width + 31) & ~31) >> 3;
    328     int		    height = xftg->metrics.height;
    329     int		    w;
    330     int		    xspan;
    331     int		    r_shift, r_len;
    332     int		    g_shift, g_len;
    333     int		    b_shift, b_len;
    334     unsigned long   pixel;
    335 
    336     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
    337     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
    338     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
    339     pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) |
    340 	     _XftPutField (color->color.green >> 8, g_shift, g_len) |
    341 	     _XftPutField (color->color.blue >> 8, b_shift, b_len));
    342     x -= xftg->metrics.x;
    343     y -= xftg->metrics.y;
    344     while (height--)
    345     {
    346 	src = srcLine;
    347 	srcLine += stride;
    348 	w = width;
    349 
    350 	bitsMask = 0x80;    /* FreeType is always MSB first */
    351 	bits = *src++;
    352 
    353 	xspan = x;
    354 	while (w--)
    355 	{
    356 	    if (bits & bitsMask)
    357 		XPutPixel (image, xspan, y, pixel);
    358     	    bitsMask = bitsMask >> 1;
    359     	    if (!bitsMask)
    360     	    {
    361     		bits = *src++;
    362     		bitsMask = 0x80;
    363     	    }
    364 	    xspan++;
    365 	}
    366 	y++;
    367     }
    368 }
    369 
    370 /*
    371  * As simple anti-aliasing is likely to be common, there are three
    372  * optimized versions for the usual true color pixel formats (888, 565, 555).
    373  * Other formats are handled by the general case
    374  */
    375 
    376 #define cvt8888to0565(s)    (CARD16)((((s) >> 3) & 0x001f) | \
    377 				     (((s) >> 5) & 0x07e0) | \
    378 				     (((s) >> 8) & 0xf800))
    379 
    380 #define cvt0565to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
    381 			     ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
    382 			     ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
    383 
    384 #define cvt8888to0555(s)    (CARD16)((((s) >> 3) & 0x001f) | \
    385 				     (((s) >> 6) & 0x03e0) | \
    386 				     (((s) >> 7) & 0x7c00))
    387 
    388 #define cvt0555to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
    389 			     ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
    390 			     ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
    391 
    392 
    393 #define XftIntMult(a,b,t,cast) \
    394         ( ((t) = (cast)((a) * (b) + 0x80)), \
    395           ( ( ( (t) >> 8 ) + (t) ) >> 8 ) )
    396 
    397 #define XftIntDiv(a,b)	 (((CARD16) (a) * 255) / (b))
    398 
    399 #define XftGet8(v,i)   ((CARD16) (CARD8) ((v) >> i))
    400 
    401 /*
    402  * There are two ways of handling alpha -- either as a single unified value or
    403  * a separate value for each component, hence each macro must have two
    404  * versions.  The unified alpha version has a 'U' at the end of the name,
    405  * the component version has a 'C'.  Similarly, functions which deal with
    406  * this difference will have two versions using the same convention.
    407  */
    408 
    409 #define XftOverU(x,y,i,a,t) \
    410         ((t) = (CARD16) XftIntMult(XftGet8(y,i),(a),(t),CARD16) + \
    411                XftGet8(x,i),\
    412          (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
    413 
    414 #define XftOverC(x,y,i,a,t) \
    415         ((t) = (CARD16) XftIntMult(XftGet8(y,i),XftGet8(a,i),(t),CARD16) + \
    416                XftGet8(x,i),\
    417          (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
    418 
    419 #define XftInU(x,i,a,t) \
    420         ((CARD32) XftIntMult(XftGet8(x,i),(a),(t),CARD16) << (i))
    421 
    422 #define XftInC(x,i,a,t) \
    423         ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t),CARD32) << (i))
    424 
    425 #define XftGen(x,y,i,ax,ay,t,u,v) \
    426         ((t) = (XftIntMult(XftGet8(y,i),ay,(u),CARD32) + \
    427                 XftIntMult(XftGet8(x,i),ax,(v),CARD32)),\
    428          (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
    429 
    430 #define XftAdd(x,y,i,t)	\
    431         ((t) = XftGet8(x,i) + XftGet8(y,i), \
    432          (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
    433 
    434 
    435 static CARD32
    436 fbOver24 (CARD32 x, CARD32 y)
    437 {
    438     CARD16  a = (CARD16)(~x >> 24);
    439     CARD16  t = 0;
    440     CARD32  m,n,o;
    441 
    442     m = XftOverU(x,y,0,a,t);
    443     n = XftOverU(x,y,8,a,t);
    444     o = XftOverU(x,y,16,a,t);
    445     return m|n|o;
    446 }
    447 
    448 static CARD32
    449 fbIn (CARD32 x, CARD8 y)
    450 {
    451     CARD16  a = y;
    452     CARD16  t;
    453     CARD32  m,n,o,p;
    454 
    455     m = XftInU(x,0,a,t);
    456     n = XftInU(x,8,a,t);
    457     o = XftInU(x,16,a,t);
    458     p = XftInU(x,24,a,t);
    459     return m|n|o|p;
    460 }
    461 
    462 static void
    463 _XftSmoothGlyphGray8888 (XImage		    *image,
    464 			 _Xconst XftGlyph   *xftg,
    465 			 int		    x,
    466 			 int		    y,
    467 			 _Xconst XftColor   *color)
    468 {
    469     CARD32	src, srca;
    470     CARD32	r, g, b;
    471     CARD32	*dstLine, *dst, d;
    472     CARD8	*maskLine, *mask, m;
    473     int		dstStride, maskStride;
    474     int		width, height;
    475     int		w;
    476 
    477     srca = color->color.alpha >> 8;
    478 
    479     /* This handles only RGB and BGR */
    480     g = (color->color.green & 0xff00);
    481     if (image->red_mask == 0xff0000)
    482     {
    483 	r = (color->color.red & 0xff00) << 8;
    484 	b = color->color.blue >> 8;
    485     }
    486     else
    487     {
    488 	r = color->color.red >> 8;
    489 	b = (color->color.blue & 0xff00) << 8;
    490     }
    491     src = (srca << 24) | r | g | b;
    492 
    493     width = xftg->metrics.width;
    494     height = xftg->metrics.height;
    495 
    496     x -= xftg->metrics.x;
    497     y -= xftg->metrics.y;
    498 
    499     dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2));
    500     dstStride = image->bytes_per_line >> 2;
    501     maskLine = (unsigned char *) xftg->bitmap;
    502     maskStride = (width + 3) & ~3;
    503 
    504     while (height--)
    505     {
    506 	dst = dstLine;
    507 	dstLine += dstStride;
    508 	mask = maskLine;
    509 	maskLine += maskStride;
    510 	w = width;
    511 
    512 	while (w--)
    513 	{
    514 	    m = *mask++;
    515 	    if (m == 0xff)
    516 	    {
    517 		if (srca == 0xff)
    518 		    *dst = src;
    519 		else
    520 		    *dst = fbOver24 (src, *dst);
    521 	    }
    522 	    else if (m)
    523 	    {
    524 		d = fbIn (src, m);
    525 		*dst = fbOver24 (d, *dst);
    526 	    }
    527 	    dst++;
    528 	}
    529     }
    530 }
    531 
    532 static void
    533 _XftSmoothGlyphGray565 (XImage		    *image,
    534 			_Xconst XftGlyph    *xftg,
    535 			int		    x,
    536 			int		    y,
    537 			_Xconst XftColor    *color)
    538 {
    539     CARD32	src, srca;
    540     CARD32	r, g, b;
    541     CARD32	d;
    542     CARD16	*dstLine, *dst;
    543     CARD8	*maskLine, *mask, m;
    544     int		dstStride, maskStride;
    545     int		width, height;
    546     int		w;
    547 
    548     srca = color->color.alpha >> 8;
    549 
    550     /* This handles only RGB and BGR */
    551     g = (color->color.green & 0xff00);
    552     if (image->red_mask == 0xf800)
    553     {
    554 	r = (color->color.red & 0xff00) << 8;
    555 	b = color->color.blue >> 8;
    556     }
    557     else
    558     {
    559 	r = color->color.red >> 8;
    560 	b = (color->color.blue & 0xff00) << 8;
    561     }
    562     src = (srca << 24) | r | g | b;
    563 
    564     width = xftg->metrics.width;
    565     height = xftg->metrics.height;
    566 
    567     x -= xftg->metrics.x;
    568     y -= xftg->metrics.y;
    569 
    570     dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
    571     dstStride = image->bytes_per_line >> 1;
    572     maskLine = (unsigned char *) xftg->bitmap;
    573     maskStride = (width + 3) & ~3;
    574 
    575     while (height--)
    576     {
    577 	dst = dstLine;
    578 	dstLine += dstStride;
    579 	mask = maskLine;
    580 	maskLine += maskStride;
    581 	w = width;
    582 
    583 	while (w--)
    584 	{
    585 	    m = *mask++;
    586 	    if (m == 0xff)
    587 	    {
    588 		if (srca == 0xff)
    589 		    d = src;
    590 		else
    591 		{
    592 		    d = *dst;
    593 		    d = fbOver24 (src, cvt0565to8888(d));
    594 		}
    595 		*dst = cvt8888to0565(d);
    596 	    }
    597 	    else if (m)
    598 	    {
    599 		d = *dst;
    600 		d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
    601 		*dst = cvt8888to0565(d);
    602 	    }
    603 	    dst++;
    604 	}
    605     }
    606 }
    607 
    608 static void
    609 _XftSmoothGlyphGray555 (XImage		    *image,
    610 			_Xconst XftGlyph    *xftg,
    611 			int		    x,
    612 			int		    y,
    613 			_Xconst XftColor    *color)
    614 {
    615     CARD32	src, srca;
    616     CARD32	r, g, b;
    617     CARD32	d;
    618     CARD16	*dstLine, *dst;
    619     CARD8	*maskLine, *mask, m;
    620     int		dstStride, maskStride;
    621     int		width, height;
    622     int		w;
    623 
    624     srca = color->color.alpha >> 8;
    625 
    626     /* This handles only RGB and BGR */
    627     g = (color->color.green & 0xff00);
    628     if (image->red_mask == 0xf800)
    629     {
    630 	r = (color->color.red & 0xff00) << 8;
    631 	b = color->color.blue >> 8;
    632     }
    633     else
    634     {
    635 	r = color->color.red >> 8;
    636 	b = (color->color.blue & 0xff00) << 8;
    637     }
    638     src = (srca << 24) | r | g | b;
    639 
    640     width = xftg->metrics.width;
    641     height = xftg->metrics.height;
    642 
    643     x -= xftg->metrics.x;
    644     y -= xftg->metrics.y;
    645 
    646     dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
    647     dstStride = image->bytes_per_line >> 1;
    648     maskLine = (unsigned char *) xftg->bitmap;
    649     maskStride = (width + 3) & ~3;
    650 
    651     while (height--)
    652     {
    653 	dst = dstLine;
    654 	dstLine += dstStride;
    655 	mask = maskLine;
    656 	maskLine += maskStride;
    657 	w = width;
    658 
    659 	while (w--)
    660 	{
    661 	    m = *mask++;
    662 	    if (m == 0xff)
    663 	    {
    664 		if (srca == 0xff)
    665 		    d = src;
    666 		else
    667 		{
    668 		    d = *dst;
    669 		    d = fbOver24 (src, cvt0555to8888(d));
    670 		}
    671 		*dst = cvt8888to0555(d);
    672 	    }
    673 	    else if (m)
    674 	    {
    675 		d = *dst;
    676 		d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
    677 		*dst = cvt8888to0555(d);
    678 	    }
    679 	    dst++;
    680 	}
    681     }
    682 }
    683 
    684 static void
    685 _XftSmoothGlyphGray (XImage		*image,
    686 		     _Xconst XftGlyph	*xftg,
    687 		     int		x,
    688 		     int		y,
    689 		     _Xconst XftColor   *color)
    690 {
    691     CARD32	    src, srca;
    692     int		    r_shift, r_len;
    693     int		    g_shift, g_len;
    694     int		    b_shift, b_len;
    695     CARD8	    *maskLine, *mask, m;
    696     int		    maskStride;
    697     CARD32	    d;
    698     unsigned long   pixel;
    699     int		    width, height;
    700     int		    w, tx;
    701 
    702     srca = color->color.alpha >> 8;
    703     src = (srca << 24 |
    704 	   (CARD32)((color->color.red & 0xff00) << 8) |
    705 	   (color->color.green & 0xff00) |
    706 	   (color->color.blue) >> 8);
    707     x -= xftg->metrics.x;
    708     y -= xftg->metrics.y;
    709     width = xftg->metrics.width;
    710     height = xftg->metrics.height;
    711 
    712     maskLine = (unsigned char *) xftg->bitmap;
    713     maskStride = (width + 3) & ~3;
    714 
    715     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
    716     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
    717     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
    718     while (height--)
    719     {
    720 	mask = maskLine;
    721 	maskLine += maskStride;
    722 	w = width;
    723 	tx = x;
    724 
    725 	while (w--)
    726 	{
    727 	    m = *mask++;
    728 	    if (m == 0xff)
    729 	    {
    730 		if (srca == 0xff)
    731 		    d = src;
    732 		else
    733 		{
    734 		    pixel = XGetPixel (image, tx, y);
    735 		    d = (_XftGetField (pixel, r_shift, r_len) << 16 |
    736 			 _XftGetField (pixel, g_shift, g_len) << 8 |
    737 			 _XftGetField (pixel, b_shift, b_len));
    738 		    d = fbOver24 (src, d);
    739 		}
    740 		pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
    741 			 _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
    742 			 _XftPutField ((d      ) & 0xff, b_shift, b_len));
    743 		XPutPixel (image, tx, y, pixel);
    744 	    }
    745 	    else if (m)
    746 	    {
    747 		pixel = XGetPixel (image, tx, y);
    748 		d = (_XftGetField (pixel, r_shift, r_len) << 16 |
    749 		     _XftGetField (pixel, g_shift, g_len) << 8 |
    750 		     _XftGetField (pixel, b_shift, b_len));
    751 		d = fbOver24 (fbIn(src,m), d);
    752 		pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
    753 			 _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
    754 			 _XftPutField ((d      ) & 0xff, b_shift, b_len));
    755 		XPutPixel (image, tx, y, pixel);
    756 	    }
    757 	    tx++;
    758 	}
    759 	y++;
    760     }
    761 }
    762 
    763 static void
    764 _XftSmoothGlyphRgba (XImage		*image,
    765 		     _Xconst XftGlyph	*xftg,
    766 		     int		x,
    767 		     int		y,
    768 		     _Xconst XftColor   *color)
    769 {
    770     CARD32	    src, srca;
    771     int		    r_shift, r_len;
    772     int		    g_shift, g_len;
    773     int		    b_shift, b_len;
    774     CARD32	    *mask, ma;
    775     CARD32	    d;
    776     unsigned long   pixel;
    777     int		    width, height;
    778     int		    w, tx;
    779 
    780     srca = color->color.alpha >> 8;
    781     src = (srca << 24 |
    782 	   (CARD32)((color->color.red & 0xff00) << 8) |
    783 	   (color->color.green & 0xff00) |
    784 	   (color->color.blue) >> 8);
    785     x -= xftg->metrics.x;
    786     y -= xftg->metrics.y;
    787     width = xftg->metrics.width;
    788     height = xftg->metrics.height;
    789 
    790     mask = (CARD32 *) xftg->bitmap;
    791 
    792     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
    793     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
    794     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
    795     while (height--)
    796     {
    797 	w = width;
    798 	tx = x;
    799 
    800 	while (w--)
    801 	{
    802 	    ma = *mask++;
    803 	    if (ma == 0xffffffff)
    804 	    {
    805 		if (srca == 0xff)
    806 		    d = src;
    807 		else
    808 		{
    809 		    pixel = XGetPixel (image, tx, y);
    810 		    d = (_XftGetField (pixel, r_shift, r_len) << 16 |
    811 			 _XftGetField (pixel, g_shift, g_len) << 8 |
    812 			 _XftGetField (pixel, b_shift, b_len));
    813 		    d = fbOver24 (src, d);
    814 		}
    815 		pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
    816 			 _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
    817 			 _XftPutField ((d      ) & 0xff, b_shift, b_len));
    818 		XPutPixel (image, tx, y, pixel);
    819 	    }
    820 	    else if (ma)
    821 	    {
    822 		CARD32	m,n,o;
    823 		pixel = XGetPixel (image, tx, y);
    824 		d = (_XftGetField (pixel, r_shift, r_len) << 16 |
    825 		     _XftGetField (pixel, g_shift, g_len) << 8 |
    826 		     _XftGetField (pixel, b_shift, b_len));
    827 #define XftInOverC(src,srca,msk,dst,i,result) { \
    828     CARD16  __a = XftGet8(msk,i); \
    829     CARD32  __t, __ta; \
    830     CARD32  __i; \
    831     __t = XftIntMult (XftGet8(src,i), __a,__i,CARD32); \
    832     __ta = (CARD8) ~XftIntMult (srca, __a,__i,CARD32); \
    833     __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i,CARD32); \
    834     __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
    835     result = __t << (i); \
    836 }
    837 		XftInOverC(src,srca,ma,d,0,m);
    838 		XftInOverC(src,srca,ma,d,8,n);
    839 		XftInOverC(src,srca,ma,d,16,o);
    840 		d = m | n | o;
    841 		pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
    842 			 _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
    843 			 _XftPutField ((d      ) & 0xff, b_shift, b_len));
    844 		XPutPixel (image, tx, y, pixel);
    845 	    }
    846 	    tx++;
    847 	}
    848 	y++;
    849     }
    850 }
    851 
    852 static FcBool
    853 _XftSmoothGlyphPossible (XftDraw *draw)
    854 {
    855     if (!draw->visual)
    856 	return FcFalse;
    857     if (draw->visual->class != TrueColor)
    858 	return FcFalse;
    859     return FcTrue;
    860 }
    861 
    862 typedef	void (*XftSmoothGlyph) (XImage		    *image,
    863 				_Xconst XftGlyph    *xftg,
    864 				int		    x,
    865 				int		    y,
    866 				_Xconst XftColor    *color);
    867 
    868 static XftSmoothGlyph
    869 _XftSmoothGlyphFind (XftDraw *draw, XftFont *public)
    870 {
    871     XftFontInt *font = (XftFontInt *) public;
    872 
    873     if (!font->info.antialias)
    874 	return _XftSmoothGlyphMono;
    875     else switch (font->info.rgba) {
    876     case FC_RGBA_RGB:
    877     case FC_RGBA_BGR:
    878     case FC_RGBA_VRGB:
    879     case FC_RGBA_VBGR:
    880 	return _XftSmoothGlyphRgba;
    881     default:
    882 	switch (XftDrawBitsPerPixel (draw)) {
    883 	case 32:
    884 	    if ((draw->visual->red_mask   == 0xff0000 &&
    885 		 draw->visual->green_mask == 0x00ff00 &&
    886 		 draw->visual->blue_mask  == 0x0000ff) ||
    887 		(draw->visual->red_mask   == 0x0000ff &&
    888 		 draw->visual->green_mask == 0x00ff00 &&
    889 		 draw->visual->blue_mask  == 0xff0000))
    890 	    {
    891 		return _XftSmoothGlyphGray8888;
    892 	    }
    893 	    break;
    894 	case 16:
    895 	    if ((draw->visual->red_mask   == 0xf800 &&
    896 		 draw->visual->green_mask == 0x07e0 &&
    897 		 draw->visual->blue_mask  == 0x001f) ||
    898 		(draw->visual->red_mask   == 0x001f &&
    899 		 draw->visual->green_mask == 0x07e0 &&
    900 		 draw->visual->blue_mask  == 0xf800))
    901 	    {
    902 		return _XftSmoothGlyphGray565;
    903 	    }
    904 	    if ((draw->visual->red_mask   == 0x7c00 &&
    905 		 draw->visual->green_mask == 0x03e0 &&
    906 		 draw->visual->blue_mask  == 0x001f) ||
    907 		(draw->visual->red_mask   == 0x001f &&
    908 		 draw->visual->green_mask == 0x03e0 &&
    909 		 draw->visual->blue_mask  == 0x7c00))
    910 	    {
    911 		return _XftSmoothGlyphGray555;
    912 	    }
    913 	    break;
    914 	default:
    915 	    break;
    916 	}
    917 	return _XftSmoothGlyphGray;
    918     }
    919 }
    920 
    921 static XftGlyph *
    922 _XftGlyphDefault (Display *dpy, XftFont   *public)
    923 {
    924     XftFontInt	    *font = (XftFontInt *) public;
    925     FT_UInt	    missing[XFT_NMISSING];
    926     int		    nmissing = 0;
    927     FcBool	    glyphs_loaded = FcFalse;
    928 
    929     if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing))
    930 	glyphs_loaded = FcTrue;
    931     if (nmissing)
    932 	XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing);
    933     return font->glyphs[0];
    934 }
    935 
    936 static int XftGetImageErrorHandler (Display *dpy _X_UNUSED, XErrorEvent *error_event _X_UNUSED)
    937 {
    938     return 0;
    939 }
    940 
    941 _X_HIDDEN void
    942 XftGlyphCore (XftDraw		*draw,
    943 	      _Xconst XftColor	*color,
    944 	      XftFont		*public,
    945 	      int		x,
    946 	      int		y,
    947 	      _Xconst FT_UInt	*glyphs,
    948 	      int		nglyphs)
    949 {
    950     Display	    *dpy = draw->dpy;
    951     XftFontInt	    *font = (XftFontInt *) public;
    952     XftGlyph	    *xftg;
    953     FT_UInt	    glyph;
    954     _Xconst FT_UInt *g;
    955     FT_UInt	    missing[XFT_NMISSING];
    956     FcBool	    glyphs_loaded;
    957     int		    nmissing;
    958     int		    n;
    959     XErrorHandler   prev_error;
    960 
    961     /*
    962      * Load missing glyphs
    963      */
    964     g = glyphs;
    965     n = nglyphs;
    966     nmissing = 0;
    967     glyphs_loaded = FcFalse;
    968     while (n--)
    969 	if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing))
    970 	    glyphs_loaded = FcTrue;
    971     if (nmissing)
    972 	XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
    973 
    974     g = glyphs;
    975     n = nglyphs;
    976     if ((font->info.antialias || color->color.alpha != 0xffff) &&
    977 	_XftSmoothGlyphPossible (draw))
    978     {
    979 	XGlyphInfo	gi;
    980 	XImage		*image;
    981         unsigned int    depth;
    982 	int		ox, oy;
    983 	XftSmoothGlyph	smooth = _XftSmoothGlyphFind (draw, public);
    984 
    985 	XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
    986 	if (!gi.width || !gi.height)
    987 	    goto bail1;
    988 	ox = x - gi.x;
    989 	oy = y - gi.y;
    990 	/*
    991 	 * Try to get bits directly from the drawable; if that fails,
    992 	 * use a temporary pixmap.  When it does fail, assume it
    993 	 * will probably fail for a while and keep using temporary
    994 	 * pixmaps for a while to avoid double round trips.
    995 	 */
    996 	if (draw->core.use_pixmap == 0)
    997 	{
    998 	    prev_error = XSetErrorHandler (XftGetImageErrorHandler);
    999 	    image = XGetImage (dpy, draw->drawable,
   1000 			       ox, oy,
   1001 			       gi.width, gi.height, AllPlanes,
   1002 			       ZPixmap);
   1003 	    XSetErrorHandler (prev_error);
   1004 	    if (!image)
   1005 		draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
   1006 	}
   1007 	else
   1008 	{
   1009 	    draw->core.use_pixmap--;
   1010 	    image = NULL;
   1011 	}
   1012 	if (!image && (depth = XftDrawDepth (draw)))
   1013 	{
   1014 	    Pixmap	pix;
   1015 	    GC		gc;
   1016 	    XGCValues	gcv;
   1017 
   1018 	    pix = XCreatePixmap (dpy, draw->drawable,
   1019 				 gi.width, gi.height, depth);
   1020 	    gcv.graphics_exposures = False;
   1021 	    gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
   1022 	    XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
   1023 		       gi.width, gi.height, 0, 0);
   1024 	    XFreeGC (dpy, gc);
   1025 	    image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
   1026 			       ZPixmap);
   1027 	    XFreePixmap (dpy, pix);
   1028 	}
   1029 	if (!image)
   1030 	    goto bail1;
   1031 	image->red_mask = draw->visual->red_mask;
   1032 	image->green_mask = draw->visual->green_mask;
   1033 	image->blue_mask = draw->visual->blue_mask;
   1034 	if (image->byte_order != XftNativeByteOrder ())
   1035 	    XftSwapImage (image);
   1036 	while (n--)
   1037 	{
   1038 	    glyph = *g++;
   1039 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1040 		xftg = _XftGlyphDefault (dpy, public);
   1041 	    if (xftg)
   1042 	    {
   1043 		(*smooth) (image, xftg, x - ox, y - oy, color);
   1044 		x += xftg->metrics.xOff;
   1045 		y += xftg->metrics.yOff;
   1046 	    }
   1047 	}
   1048 	if (image->byte_order != XftNativeByteOrder ())
   1049 	    XftSwapImage (image);
   1050 	XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
   1051 		   gi.width, gi.height);
   1052 	XDestroyImage (image);
   1053     }
   1054     else
   1055     {
   1056 	XftSharpGlyph	sharp = _XftSharpGlyphFind (draw, public);
   1057 	while (n--)
   1058 	{
   1059 	    glyph = *g++;
   1060 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1061 		xftg = _XftGlyphDefault (dpy, public);
   1062 	    if (xftg)
   1063 	    {
   1064 		(*sharp) (draw, xftg, x, y);
   1065 		x += xftg->metrics.xOff;
   1066 		y += xftg->metrics.yOff;
   1067 	    }
   1068 	}
   1069     }
   1070 bail1:
   1071     if (glyphs_loaded)
   1072 	_XftFontManageMemory (dpy, public);
   1073 }
   1074 
   1075 #define NUM_LOCAL   1024
   1076 
   1077 _X_HIDDEN void
   1078 XftGlyphSpecCore (XftDraw		*draw,
   1079 		  _Xconst XftColor	*color,
   1080 		  XftFont		*public,
   1081 		  _Xconst XftGlyphSpec	*glyphs,
   1082 		  int			nglyphs)
   1083 {
   1084     Display	    *dpy = draw->dpy;
   1085     XftFontInt	    *font = (XftFontInt *) public;
   1086     XftGlyph	    *xftg;
   1087     FT_UInt	    missing[XFT_NMISSING];
   1088     FcBool	    glyphs_loaded;
   1089     int		    nmissing;
   1090     int		    i;
   1091     XErrorHandler   prev_error;
   1092     int		    x1, y1, x2, y2;
   1093 
   1094     /*
   1095      * Load missing glyphs
   1096      */
   1097     glyphs_loaded = FcFalse;
   1098     x1 = y1 = x2 = y2 = 0;
   1099     for (i = 0; i < nglyphs; i++)
   1100     {
   1101 	XGlyphInfo	gi;
   1102 	int		g_x1, g_x2, g_y1, g_y2;
   1103 
   1104 	nmissing = 0;
   1105 	if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
   1106 	    glyphs_loaded = FcTrue;
   1107 	if (nmissing)
   1108 	    XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
   1109 
   1110 	XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
   1111 	g_x1 = glyphs[i].x - gi.x;
   1112 	g_y1 = glyphs[i].y - gi.y;
   1113 	g_x2 = g_x1 + gi.width;
   1114 	g_y2 = g_y1 + gi.height;
   1115 	if (i)
   1116 	{
   1117 	    if (g_x1 < x1)
   1118 		x1 = g_x1;
   1119 	    if (g_y1 < y1)
   1120 		y1 = g_y1;
   1121 	    if (g_x2 > x2)
   1122 		x2 = g_x2;
   1123 	    if (g_y2 > y2)
   1124 		y2 = g_y2;
   1125 	}
   1126 	else
   1127 	{
   1128 	    x1 = g_x1;
   1129 	    y1 = g_y1;
   1130 	    x2 = g_x2;
   1131 	    y2 = g_y2;
   1132 	}
   1133     }
   1134 
   1135     if (x1 == x2 || y1 == y2)
   1136 	goto bail1;
   1137 
   1138     if ((font->info.antialias || color->color.alpha != 0xffff) &&
   1139 	_XftSmoothGlyphPossible (draw))
   1140     {
   1141 	XImage		*image;
   1142         unsigned int    depth;
   1143 	int		width = x2 - x1, height = y2 - y1;
   1144 	XftSmoothGlyph	smooth = _XftSmoothGlyphFind (draw, public);
   1145 
   1146 	/*
   1147 	 * Try to get bits directly from the drawable; if that fails,
   1148 	 * use a temporary pixmap.  When it does fail, assume it
   1149 	 * will probably fail for a while and keep using temporary
   1150 	 * pixmaps for a while to avoid double round trips.
   1151 	 */
   1152 	if (draw->core.use_pixmap == 0)
   1153 	{
   1154 	    prev_error = XSetErrorHandler (XftGetImageErrorHandler);
   1155 	    image = XGetImage (dpy, draw->drawable,
   1156 			       x1, y1,
   1157 			       (unsigned)width, (unsigned)height, AllPlanes,
   1158 			       ZPixmap);
   1159 	    XSetErrorHandler (prev_error);
   1160 	    if (!image)
   1161 		draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
   1162 	}
   1163 	else
   1164 	{
   1165 	    draw->core.use_pixmap--;
   1166 	    image = NULL;
   1167 	}
   1168 	if (!image && (depth = XftDrawDepth (draw)))
   1169 	{
   1170 	    Pixmap	pix;
   1171 	    GC		gc;
   1172 	    XGCValues	gcv;
   1173 
   1174 	    pix = XCreatePixmap (dpy, draw->drawable,
   1175 				 (unsigned)width, (unsigned)height, depth);
   1176 	    gcv.graphics_exposures = False;
   1177 	    gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
   1178 	    XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
   1179 		       (unsigned)width, (unsigned)height, 0, 0);
   1180 	    XFreeGC (dpy, gc);
   1181 	    image = XGetImage (dpy, pix, 0, 0, (unsigned)width, (unsigned)height, AllPlanes,
   1182 			       ZPixmap);
   1183 	    XFreePixmap (dpy, pix);
   1184 	}
   1185 	if (!image)
   1186 	    goto bail1;
   1187 	image->red_mask = draw->visual->red_mask;
   1188 	image->green_mask = draw->visual->green_mask;
   1189 	image->blue_mask = draw->visual->blue_mask;
   1190 	if (image->byte_order != XftNativeByteOrder ())
   1191 	    XftSwapImage (image);
   1192 	for (i = 0; i < nglyphs; i++)
   1193 	{
   1194 	    FT_UInt glyph = glyphs[i].glyph;
   1195 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1196 		xftg = _XftGlyphDefault (dpy, public);
   1197 	    if (xftg)
   1198 	    {
   1199 		(*smooth) (image, xftg, glyphs[i].x - x1,
   1200 			   glyphs[i].y - y1, color);
   1201 	    }
   1202 	}
   1203 	if (image->byte_order != XftNativeByteOrder ())
   1204 	    XftSwapImage (image);
   1205 	XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
   1206 		   (unsigned)width, (unsigned)height);
   1207 	XDestroyImage (image);
   1208     }
   1209     else
   1210     {
   1211 	XftSharpGlyph	sharp = _XftSharpGlyphFind (draw, public);
   1212 	for (i = 0; i < nglyphs; i++)
   1213 	{
   1214 	    FT_UInt glyph = glyphs[i].glyph;
   1215 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1216 		xftg = _XftGlyphDefault (dpy, public);
   1217 	    if (xftg)
   1218 		(*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
   1219 	}
   1220     }
   1221 bail1:
   1222     if (glyphs_loaded)
   1223 	_XftFontManageMemory (dpy, public);
   1224 }
   1225 
   1226 _X_HIDDEN void
   1227 XftGlyphFontSpecCore (XftDraw			*draw,
   1228 		      _Xconst XftColor		*color,
   1229 		      _Xconst XftGlyphFontSpec	*glyphs,
   1230 		      int			nglyphs)
   1231 {
   1232     Display	    *dpy = draw->dpy;
   1233     XftGlyph	    *xftg;
   1234     FT_UInt	    missing[XFT_NMISSING];
   1235     FcBool	    glyphs_loaded;
   1236     int		    nmissing;
   1237     int		    i;
   1238     XErrorHandler   prev_error;
   1239     int		    x1, y1, x2, y2;
   1240 
   1241     /*
   1242      * Load missing glyphs
   1243      */
   1244     glyphs_loaded = FcFalse;
   1245     x1 = y1 = x2 = y2 = 0;
   1246     for (i = 0; i < nglyphs; i++)
   1247     {
   1248 	XftFont		*public = glyphs[i].font;
   1249 	XGlyphInfo	gi;
   1250 	int		g_x1, g_x2, g_y1, g_y2;
   1251 
   1252 	nmissing = 0;
   1253 	if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
   1254 	    glyphs_loaded = FcTrue;
   1255 	if (nmissing)
   1256 	    XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
   1257 
   1258 	XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
   1259 	g_x1 = glyphs[i].x - gi.x;
   1260 	g_y1 = glyphs[i].y - gi.y;
   1261 	g_x2 = g_x1 + gi.width;
   1262 	g_y2 = g_y1 + gi.height;
   1263 	if (i)
   1264 	{
   1265 	    if (g_x1 < x1)
   1266 	    {
   1267 		if (g_x1 < 0)
   1268 		{
   1269 		    /* do nothing if the given glyphs are out of range */
   1270 		    short t = (short)(glyphs[i-1].font->max_advance_width
   1271 				      + glyphs[i-1].x);
   1272 		    if (t < 0 && glyphs[i-1].x > 0)
   1273 			goto bail1;
   1274 		}
   1275 		x1 = g_x1;
   1276 	    }
   1277 	    if (g_y1 < y1)
   1278 		y1 = g_y1;
   1279 	    if (g_x2 > x2)
   1280 		x2 = g_x2;
   1281 	    if (g_y2 > y2)
   1282 		y2 = g_y2;
   1283 	}
   1284 	else
   1285 	{
   1286 	    x1 = g_x1;
   1287 	    y1 = g_y1;
   1288 	    x2 = g_x2;
   1289 	    y2 = g_y2;
   1290 	}
   1291     }
   1292 
   1293     if (x1 == x2 || y1 == y2)
   1294 	goto bail1;
   1295 
   1296     for (i = 0; i < nglyphs; i++)
   1297 	if (((XftFontInt *) glyphs[i].font)->info.antialias)
   1298 	    break;
   1299 
   1300     if ((i != nglyphs || color->color.alpha != 0xffff) &&
   1301 	_XftSmoothGlyphPossible (draw))
   1302     {
   1303 	XImage		*image;
   1304         unsigned int    depth;
   1305 	int		width = x2 - x1, height = y2 - y1;
   1306 
   1307 	/*
   1308 	 * Try to get bits directly from the drawable; if that fails,
   1309 	 * use a temporary pixmap.  When it does fail, assume it
   1310 	 * will probably fail for a while and keep using temporary
   1311 	 * pixmaps for a while to avoid double round trips.
   1312 	 */
   1313 	if (draw->core.use_pixmap == 0)
   1314 	{
   1315 	    prev_error = XSetErrorHandler (XftGetImageErrorHandler);
   1316 	    image = XGetImage (dpy, draw->drawable,
   1317 			       x1, y1,
   1318 			       (unsigned)width, (unsigned)height, AllPlanes,
   1319 			       ZPixmap);
   1320 	    XSetErrorHandler (prev_error);
   1321 	    if (!image)
   1322 		draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
   1323 	}
   1324 	else
   1325 	{
   1326 	    draw->core.use_pixmap--;
   1327 	    image = NULL;
   1328 	}
   1329 	if (!image && (depth = XftDrawDepth (draw)))
   1330 	{
   1331 	    Pixmap	pix;
   1332 	    GC		gc;
   1333 	    XGCValues	gcv;
   1334 
   1335 	    pix = XCreatePixmap (dpy, draw->drawable,
   1336 				 (unsigned)width, (unsigned)height, depth);
   1337 	    gcv.graphics_exposures = False;
   1338 	    gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
   1339 	    XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
   1340 		       (unsigned)width, (unsigned)height, 0, 0);
   1341 	    XFreeGC (dpy, gc);
   1342 	    image = XGetImage (dpy, pix, 0, 0, (unsigned)width, (unsigned)height, AllPlanes,
   1343 			       ZPixmap);
   1344 	    XFreePixmap (dpy, pix);
   1345 	}
   1346 	if (!image)
   1347 	    goto bail1;
   1348 	image->red_mask = draw->visual->red_mask;
   1349 	image->green_mask = draw->visual->green_mask;
   1350 	image->blue_mask = draw->visual->blue_mask;
   1351 	if (image->byte_order != XftNativeByteOrder ())
   1352 	    XftSwapImage (image);
   1353 	for (i = 0; i < nglyphs; i++)
   1354 	{
   1355 	    XftFont	    *public = glyphs[i].font;
   1356 	    XftFontInt	    *font = (XftFontInt *) public;
   1357 	    XftSmoothGlyph  smooth = _XftSmoothGlyphFind (draw, public);
   1358 	    FT_UInt	    glyph = glyphs[i].glyph;
   1359 
   1360 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1361 		xftg = _XftGlyphDefault (dpy, public);
   1362 	    if (xftg)
   1363 	    {
   1364 		(*smooth) (image, xftg, glyphs[i].x - x1,
   1365 			   glyphs[i].y - y1, color);
   1366 	    }
   1367 	}
   1368 	if (image->byte_order != XftNativeByteOrder ())
   1369 	    XftSwapImage (image);
   1370 	XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
   1371 		   (unsigned)width, (unsigned)height);
   1372 	XDestroyImage (image);
   1373     }
   1374     else
   1375     {
   1376 	for (i = 0; i < nglyphs; i++)
   1377 	{
   1378 	    XftFont		*public = glyphs[i].font;
   1379 	    XftFontInt		*font = (XftFontInt *) public;
   1380 	    XftSharpGlyph	sharp = _XftSharpGlyphFind (draw, public);
   1381 	    FT_UInt		glyph = glyphs[i].glyph;
   1382 
   1383 	    if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
   1384 		xftg = _XftGlyphDefault (dpy, public);
   1385 	    if (xftg)
   1386 		(*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
   1387 	}
   1388     }
   1389 bail1:
   1390     if (glyphs_loaded)
   1391 	for (i = 0; i < nglyphs; i++)
   1392 	    _XftFontManageMemory (dpy, glyphs[i].font);
   1393 }
   1394