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