xftglyphs.c revision 0e0b1094
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"
247bbb83baSmrg#include FT_OUTLINE_H
2512d4a5f4Smrg#include FT_LCD_FILTER_H
267bbb83baSmrg
2712d4a5f4Smrg#include FT_SYNTHESIS_H
28c76ae52dSmrg
29c76ae52dSmrg/*
30c76ae52dSmrg * Validate the memory info for a font
31c76ae52dSmrg */
32c76ae52dSmrg
33c76ae52dSmrgstatic void
34c76ae52dSmrg_XftFontValidateMemory (Display *dpy, XftFont *public)
35c76ae52dSmrg{
36c76ae52dSmrg    XftFontInt	    *font = (XftFontInt *) public;
37c76ae52dSmrg    unsigned long   glyph_memory;
38c76ae52dSmrg    FT_UInt	    glyphindex;
39c76ae52dSmrg    XftGlyph	    *xftg;
40c76ae52dSmrg
41c76ae52dSmrg    glyph_memory = 0;
42c76ae52dSmrg    for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
43c76ae52dSmrg    {
44c76ae52dSmrg	xftg = font->glyphs[glyphindex];
45c76ae52dSmrg	if (xftg)
46c76ae52dSmrg	{
47c76ae52dSmrg	    glyph_memory += xftg->glyph_memory;
48c76ae52dSmrg	}
49c76ae52dSmrg    }
50c76ae52dSmrg    if (glyph_memory != font->glyph_memory)
51c76ae52dSmrg	printf ("Font glyph cache incorrect has %ld bytes, should have %ld\n",
52c76ae52dSmrg		font->glyph_memory, glyph_memory);
53c76ae52dSmrg}
54c76ae52dSmrg
552836776bSmrg/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
562836776bSmrg * into a different format. For example, we want to convert a
572836776bSmrg * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
582836776bSmrg * ARGB or ABGR bitmap.
592836776bSmrg *
602836776bSmrg * this function prepares a target descriptor for this operation.
612836776bSmrg *
622836776bSmrg * input :: target bitmap descriptor. The function will set its
632836776bSmrg *          'width', 'rows' and 'pitch' fields, and only these
642836776bSmrg *
652836776bSmrg * slot  :: the glyph slot containing the source bitmap. this
662836776bSmrg *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
672836776bSmrg *
682836776bSmrg * mode  :: the requested final rendering mode. supported values are
692836776bSmrg *          MONO, NORMAL (i.e. gray), LCD and LCD_V
702836776bSmrg *
712836776bSmrg * the function returns the size in bytes of the corresponding buffer,
722836776bSmrg * it's up to the caller to allocate the corresponding memory block
732836776bSmrg * before calling _fill_xrender_bitmap
742836776bSmrg *
752836776bSmrg * it also returns -1 in case of error (e.g. incompatible arguments,
762836776bSmrg * like trying to convert a gray bitmap into a monochrome one)
772836776bSmrg */
782836776bSmrgstatic int
792836776bSmrg_compute_xrender_bitmap_size( FT_Bitmap*	target,
802836776bSmrg			      FT_GlyphSlot	slot,
812836776bSmrg			      FT_Render_Mode	mode )
822836776bSmrg{
832836776bSmrg    FT_Bitmap*	ftbit;
842836776bSmrg    int		width, height, pitch;
852836776bSmrg
862836776bSmrg    if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
872836776bSmrg	return -1;
882836776bSmrg
890e0b1094Smrg    /* compute the size of the final bitmap */
902836776bSmrg    ftbit = &slot->bitmap;
912836776bSmrg
920e0b1094Smrg    width = (int)ftbit->width;
930e0b1094Smrg    height = (int)ftbit->rows;
942836776bSmrg    pitch = (width+3) & ~3;
952836776bSmrg
962836776bSmrg    switch ( ftbit->pixel_mode )
972836776bSmrg    {
982836776bSmrg    case FT_PIXEL_MODE_MONO:
992836776bSmrg	if ( mode == FT_RENDER_MODE_MONO )
1002836776bSmrg	{
1012836776bSmrg	    pitch = (((width+31) & ~31) >> 3);
1022836776bSmrg	    break;
1032836776bSmrg	}
1042836776bSmrg	/* fall-through */
1052836776bSmrg
1062836776bSmrg    case FT_PIXEL_MODE_GRAY:
1072836776bSmrg	if ( mode == FT_RENDER_MODE_LCD ||
1082836776bSmrg	     mode == FT_RENDER_MODE_LCD_V )
1092836776bSmrg	{
1102836776bSmrg	    /* each pixel is replicated into a 32-bit ARGB value */
1112836776bSmrg	    pitch = width*4;
1122836776bSmrg	}
1132836776bSmrg	break;
1142836776bSmrg
1152836776bSmrg    case FT_PIXEL_MODE_LCD:
1162836776bSmrg	if ( mode != FT_RENDER_MODE_LCD )
1172836776bSmrg	    return -1;
1182836776bSmrg
1192836776bSmrg	/* horz pixel triplets are packed into 32-bit ARGB values */
1202836776bSmrg	width /= 3;
1212836776bSmrg	pitch = width*4;
1222836776bSmrg	break;
1232836776bSmrg
1242836776bSmrg    case FT_PIXEL_MODE_LCD_V:
1252836776bSmrg	if ( mode != FT_RENDER_MODE_LCD_V )
1262836776bSmrg	    return -1;
1272836776bSmrg
1282836776bSmrg	/* vert pixel triplets are packed into 32-bit ARGB values */
1292836776bSmrg	height /= 3;
1302836776bSmrg	pitch = width*4;
1312836776bSmrg	break;
1322836776bSmrg
1332836776bSmrg    default:  /* unsupported source format */
1342836776bSmrg	return -1;
1352836776bSmrg    }
1362836776bSmrg
1370e0b1094Smrg    target->width = (unsigned)width;
1380e0b1094Smrg    target->rows = (unsigned)height;
1392836776bSmrg    target->pitch = pitch;
1402836776bSmrg    target->buffer = NULL;
1412836776bSmrg
1422836776bSmrg    return pitch * height;
1432836776bSmrg}
1442836776bSmrg
1452836776bSmrg/* this functions converts the glyph bitmap found in a FT_GlyphSlot
1462836776bSmrg * into a different format (see _compute_xrender_bitmap_size)
1472836776bSmrg *
1482836776bSmrg * you should call this function after _compute_xrender_bitmap_size
1492836776bSmrg *
1502836776bSmrg * target :: target bitmap descriptor. Note that its 'buffer' pointer
1512836776bSmrg *           must point to memory allocated by the caller
1522836776bSmrg *
1532836776bSmrg * slot   :: the glyph slot containing the source bitmap
1542836776bSmrg *
1552836776bSmrg * mode   :: the requested final rendering mode
1562836776bSmrg *
1572836776bSmrg * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
1582836776bSmrg */
1592836776bSmrgstatic void
1602836776bSmrg_fill_xrender_bitmap( FT_Bitmap*	target,
1612836776bSmrg		      FT_GlyphSlot	slot,
1622836776bSmrg		      FT_Render_Mode	mode,
1632836776bSmrg		      int		bgr )
1642836776bSmrg{
1652836776bSmrg    FT_Bitmap*   ftbit = &slot->bitmap;
1662836776bSmrg
1672836776bSmrg    {
1682836776bSmrg	unsigned char*	srcLine	= ftbit->buffer;
1692836776bSmrg        unsigned char*	dstLine	= target->buffer;
1702836776bSmrg        int		src_pitch = ftbit->pitch;
1710e0b1094Smrg        int		width = (int)target->width;
1720e0b1094Smrg        int		height = (int)target->rows;
1732836776bSmrg        int		pitch = target->pitch;
1742836776bSmrg        int		subpixel;
1752836776bSmrg        int		h;
1762836776bSmrg
1772836776bSmrg        subpixel = ( mode == FT_RENDER_MODE_LCD ||
1782836776bSmrg		     mode == FT_RENDER_MODE_LCD_V );
1792836776bSmrg
1802836776bSmrg	if ( src_pitch < 0 )
1810e0b1094Smrg	    srcLine -= ((unsigned)src_pitch * (ftbit->rows-1));
1822836776bSmrg
1832836776bSmrg	switch ( ftbit->pixel_mode )
1842836776bSmrg	{
1852836776bSmrg	case FT_PIXEL_MODE_MONO:
1862836776bSmrg	    if ( subpixel )  /* convert mono to ARGB32 values */
1872836776bSmrg	    {
1882836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
1892836776bSmrg		{
1902836776bSmrg		    int x;
1912836776bSmrg
1922836776bSmrg		    for ( x = 0; x < width; x++ )
1932836776bSmrg		    {
1942836776bSmrg			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
1952836776bSmrg			    ((unsigned int*)dstLine)[x] = 0xffffffffU;
1962836776bSmrg		    }
1972836776bSmrg		}
1982836776bSmrg	    }
1992836776bSmrg	    else if ( mode == FT_RENDER_MODE_NORMAL )  /* convert mono to 8-bit gray */
2002836776bSmrg	    {
2012836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2022836776bSmrg		{
2032836776bSmrg		    int x;
2042836776bSmrg
2052836776bSmrg		    for ( x = 0; x < width; x++ )
2062836776bSmrg		    {
2072836776bSmrg			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
2082836776bSmrg			    dstLine[x] = 0xff;
2092836776bSmrg		    }
2102836776bSmrg		}
2112836776bSmrg	    }
2122836776bSmrg	    else  /* copy mono to mono */
2132836776bSmrg	    {
2142836776bSmrg		int bytes = (width+7) >> 3;
2152836776bSmrg
2162836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2170e0b1094Smrg		    memcpy( dstLine, srcLine, (size_t)bytes );
2182836776bSmrg	    }
2192836776bSmrg	    break;
2202836776bSmrg
2212836776bSmrg	case FT_PIXEL_MODE_GRAY:
2222836776bSmrg	    if ( subpixel )  /* convert gray to ARGB32 values */
2232836776bSmrg	    {
2242836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2252836776bSmrg		{
2262836776bSmrg		    int		   x;
2272836776bSmrg		    unsigned int*  dst = (unsigned int*)dstLine;
2282836776bSmrg
2292836776bSmrg		    for ( x = 0; x < width; x++ )
2302836776bSmrg		    {
2312836776bSmrg			unsigned int pix = srcLine[x];
2322836776bSmrg
2332836776bSmrg			pix |= (pix << 8);
2342836776bSmrg			pix |= (pix << 16);
2352836776bSmrg
2362836776bSmrg			dst[x] = pix;
2372836776bSmrg		    }
2382836776bSmrg		}
2392836776bSmrg	    }
2402836776bSmrg	    else  /* copy gray into gray */
2412836776bSmrg	    {
2422836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2430e0b1094Smrg		    memcpy( dstLine, srcLine, (size_t)width );
2442836776bSmrg	    }
2452836776bSmrg	    break;
2462836776bSmrg
2472836776bSmrg	case FT_PIXEL_MODE_LCD:
2482836776bSmrg	    if ( !bgr )
2492836776bSmrg	    {
2502836776bSmrg		/* convert horizontal RGB into ARGB32 */
2512836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2522836776bSmrg		{
2532836776bSmrg		    int		   x;
2542836776bSmrg		    unsigned char* src = srcLine;
2552836776bSmrg		    unsigned int*  dst = (unsigned int*)dstLine;
2562836776bSmrg
2572836776bSmrg		    for ( x = 0; x < width; x++, src += 3 )
2582836776bSmrg		    {
2592836776bSmrg			unsigned int pix;
2602836776bSmrg
2612836776bSmrg			pix = ((unsigned int)src[0] << 16) |
2622836776bSmrg			      ((unsigned int)src[1] <<  8) |
2632836776bSmrg			      ((unsigned int)src[2]      ) |
2642836776bSmrg			      ((unsigned int)src[1] << 24) ;
2652836776bSmrg
2662836776bSmrg			dst[x] = pix;
2672836776bSmrg		    }
2682836776bSmrg		}
2692836776bSmrg	    }
2702836776bSmrg	    else
2712836776bSmrg	    {
2722836776bSmrg		/* convert horizontal BGR into ARGB32 */
2732836776bSmrg		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
2742836776bSmrg		{
2752836776bSmrg		    int		   x;
2762836776bSmrg		    unsigned char* src = srcLine;
2772836776bSmrg		    unsigned int*  dst = (unsigned int*)dstLine;
2782836776bSmrg
2792836776bSmrg		    for ( x = 0; x < width; x++, src += 3 )
2802836776bSmrg		    {
2812836776bSmrg			unsigned int pix;
2822836776bSmrg
2832836776bSmrg			pix = ((unsigned int)src[2] << 16) |
2842836776bSmrg			      ((unsigned int)src[1] <<  8) |
2852836776bSmrg			      ((unsigned int)src[0]      ) |
2862836776bSmrg			      ((unsigned int)src[1] << 24) ;
2872836776bSmrg
2882836776bSmrg			dst[x] = pix;
2892836776bSmrg		    }
2902836776bSmrg		}
2912836776bSmrg	    }
2922836776bSmrg	    break;
2932836776bSmrg
2942836776bSmrg	default:  /* FT_PIXEL_MODE_LCD_V */
2952836776bSmrg	    /* convert vertical RGB into ARGB32 */
2962836776bSmrg	    if ( !bgr )
2972836776bSmrg	    {
2982836776bSmrg		for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
2992836776bSmrg		{
3002836776bSmrg		    int		   x;
3012836776bSmrg		    unsigned char* src = srcLine;
3022836776bSmrg		    unsigned int*  dst = (unsigned int*)dstLine;
3032836776bSmrg
3042836776bSmrg		    for ( x = 0; x < width; x++, src += 1 )
3052836776bSmrg		    {
3062836776bSmrg			unsigned int  pix;
3072836776bSmrg
3082836776bSmrg			pix = ((unsigned int)src[0]           << 16) |
3092836776bSmrg			      ((unsigned int)src[src_pitch]   <<  8) |
3102836776bSmrg			      ((unsigned int)src[src_pitch*2]      ) |
3112836776bSmrg			      ((unsigned int)src[src_pitch]   << 24) ;
3122836776bSmrg
3132836776bSmrg			dst[x] = pix;
3142836776bSmrg		    }
3152836776bSmrg		}
3162836776bSmrg	    }
3172836776bSmrg	    else
3182836776bSmrg	    {
3192836776bSmrg	    for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
3202836776bSmrg		{
3212836776bSmrg		    int		   x;
3222836776bSmrg		    unsigned char* src = srcLine;
3232836776bSmrg		    unsigned int*  dst = (unsigned int*)dstLine;
3242836776bSmrg
3252836776bSmrg		    for ( x = 0; x < width; x++, src += 1 )
3262836776bSmrg		    {
3272836776bSmrg			unsigned int  pix;
3282836776bSmrg
3292836776bSmrg			pix = ((unsigned int)src[src_pitch*2] << 16) |
3302836776bSmrg			      ((unsigned int)src[src_pitch]   <<  8) |
3312836776bSmrg			      ((unsigned int)src[0]                ) |
3322836776bSmrg			      ((unsigned int)src[src_pitch]   << 24) ;
3332836776bSmrg
3342836776bSmrg			dst[x] = pix;
3352836776bSmrg		    }
3362836776bSmrg		}
3372836776bSmrg	    }
3382836776bSmrg	}
3392836776bSmrg    }
3402836776bSmrg}
3412836776bSmrg
342c76ae52dSmrg_X_EXPORT void
343c76ae52dSmrgXftFontLoadGlyphs (Display	    *dpy,
344c76ae52dSmrg		   XftFont	    *pub,
345c76ae52dSmrg		   FcBool	    need_bitmaps,
346c76ae52dSmrg		   _Xconst FT_UInt  *glyphs,
347c76ae52dSmrg		   int		    nglyph)
348c76ae52dSmrg{
349c76ae52dSmrg    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
350c76ae52dSmrg    XftFontInt	    *font = (XftFontInt *) pub;
351c76ae52dSmrg    FT_Error	    error;
352c76ae52dSmrg    FT_UInt	    glyphindex;
353c76ae52dSmrg    FT_GlyphSlot    glyphslot;
354c76ae52dSmrg    XftGlyph	    *xftg;
355c76ae52dSmrg    Glyph	    glyph;
356c76ae52dSmrg    unsigned char   bufLocal[4096];
357c76ae52dSmrg    unsigned char   *bufBitmap = bufLocal;
358c76ae52dSmrg    int		    bufSize = sizeof (bufLocal);
3592836776bSmrg    int		    size;
360c76ae52dSmrg    int		    width;
361c76ae52dSmrg    int		    height;
362c76ae52dSmrg    int		    left, right, top, bottom;
3632836776bSmrg    FT_Bitmap*	    ftbit;
3642836776bSmrg    FT_Bitmap	    local;
365c76ae52dSmrg    FT_Vector	    vector;
366c76ae52dSmrg    FT_Face	    face;
3672836776bSmrg    FT_Render_Mode  mode = FT_RENDER_MODE_MONO;
368c76ae52dSmrg
369c76ae52dSmrg    if (!info)
370c76ae52dSmrg	return;
371c76ae52dSmrg
372c76ae52dSmrg    face = XftLockFace (&font->public);
3732836776bSmrg
374c76ae52dSmrg    if (!face)
375c76ae52dSmrg	return;
376c76ae52dSmrg
377c76ae52dSmrg    if (font->info.antialias)
378c76ae52dSmrg    {
379c76ae52dSmrg	switch (font->info.rgba) {
380c76ae52dSmrg	case FC_RGBA_RGB:
381c76ae52dSmrg	case FC_RGBA_BGR:
3822836776bSmrg	    mode = FT_RENDER_MODE_LCD;
383c76ae52dSmrg	    break;
384c76ae52dSmrg	case FC_RGBA_VRGB:
385c76ae52dSmrg	case FC_RGBA_VBGR:
3862836776bSmrg	    mode = FT_RENDER_MODE_LCD_V;
387c76ae52dSmrg	    break;
3882836776bSmrg	default:
3892836776bSmrg	    mode = FT_RENDER_MODE_NORMAL;
390c76ae52dSmrg	}
391c76ae52dSmrg    }
392c76ae52dSmrg
393c76ae52dSmrg    while (nglyph--)
394c76ae52dSmrg    {
395c76ae52dSmrg	glyphindex = *glyphs++;
396c76ae52dSmrg	xftg = font->glyphs[glyphindex];
397c76ae52dSmrg	if (!xftg)
398c76ae52dSmrg	    continue;
3992836776bSmrg
400c76ae52dSmrg	if (XftDebug() & XFT_DBG_CACHE)
401c76ae52dSmrg	    _XftFontValidateMemory (dpy, pub);
402c76ae52dSmrg	/*
403c76ae52dSmrg	 * Check to see if this glyph has just been loaded,
404c76ae52dSmrg	 * this happens when drawing the same glyph twice
405c76ae52dSmrg	 * in a single string
406c76ae52dSmrg	 */
407c76ae52dSmrg	if (xftg->glyph_memory)
408c76ae52dSmrg	    continue;
4092836776bSmrg
4102836776bSmrg	FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter);
4112836776bSmrg
412c76ae52dSmrg	error = FT_Load_Glyph (face, glyphindex, font->info.load_flags);
413c76ae52dSmrg	if (error)
414c76ae52dSmrg	{
415c76ae52dSmrg	    /*
416c76ae52dSmrg	     * If anti-aliasing or transforming glyphs and
417c76ae52dSmrg	     * no outline version exists, fallback to the
418c76ae52dSmrg	     * bitmap and let things look bad instead of
419c76ae52dSmrg	     * missing the glyph
420c76ae52dSmrg	     */
421c76ae52dSmrg	    if (font->info.load_flags & FT_LOAD_NO_BITMAP)
422c76ae52dSmrg		error = FT_Load_Glyph (face, glyphindex,
423c76ae52dSmrg				       font->info.load_flags & ~FT_LOAD_NO_BITMAP);
424c76ae52dSmrg	    if (error)
425c76ae52dSmrg		continue;
426c76ae52dSmrg	}
427c76ae52dSmrg
428c76ae52dSmrg#define FLOOR(x)    ((x) & -64)
429c76ae52dSmrg#define CEIL(x)	    (((x)+63) & -64)
430c76ae52dSmrg#define TRUNC(x)    ((x) >> 6)
431c76ae52dSmrg#define ROUND(x)    (((x)+32) & -64)
4322836776bSmrg
433c76ae52dSmrg	glyphslot = face->glyph;
434c76ae52dSmrg
435c76ae52dSmrg	/*
436c76ae52dSmrg	 * Embolden if required
437c76ae52dSmrg	 */
438c76ae52dSmrg	if (font->info.embolden) FT_GlyphSlot_Embolden(glyphslot);
439c76ae52dSmrg
440c76ae52dSmrg	/*
441c76ae52dSmrg	 * Compute glyph metrics from FreeType information
442c76ae52dSmrg	 */
4432836776bSmrg	if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
444c76ae52dSmrg	{
445c76ae52dSmrg	    /*
446c76ae52dSmrg	     * calculate the true width by transforming all four corners.
447c76ae52dSmrg	     */
448c76ae52dSmrg	    int xc, yc;
449c76ae52dSmrg	    left = right = top = bottom = 0;
450c76ae52dSmrg	    for(xc = 0; xc <= 1; xc ++) {
451c76ae52dSmrg		for(yc = 0; yc <= 1; yc++) {
452c76ae52dSmrg		    vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width;
453c76ae52dSmrg		    vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height;
4542836776bSmrg		    FT_Vector_Transform(&vector, &font->info.matrix);
455c76ae52dSmrg		    if (XftDebug() & XFT_DBG_GLYPH)
4562836776bSmrg			printf("Trans %d %d: %d %d\n", (int) xc, (int) yc,
457c76ae52dSmrg			       (int) vector.x, (int) vector.y);
458c76ae52dSmrg		    if(xc == 0 && yc == 0) {
4590e0b1094Smrg			left = right = (int)vector.x;
4600e0b1094Smrg			top = bottom = (int)vector.y;
461c76ae52dSmrg		    } else {
4620e0b1094Smrg			if(left	  > vector.x) left   = (int)vector.x;
4630e0b1094Smrg			if(right  < vector.x) right  = (int)vector.x;
4640e0b1094Smrg			if(bottom > vector.y) bottom = (int)vector.y;
4650e0b1094Smrg			if(top	  < vector.y) top    = (int)vector.y;
466c76ae52dSmrg		    }
467c76ae52dSmrg
468c76ae52dSmrg		}
469c76ae52dSmrg	    }
4700e0b1094Smrg	    left   = (int)FLOOR(left);
4710e0b1094Smrg	    right  = (int)CEIL(right);
4720e0b1094Smrg	    bottom = (int)FLOOR(bottom);
4730e0b1094Smrg	    top	   = CEIL(top);
474c76ae52dSmrg
475c76ae52dSmrg	} else {
4760e0b1094Smrg	    left   = (int)FLOOR( glyphslot->metrics.horiBearingX );
4770e0b1094Smrg	    right  = (int)CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width );
478c76ae52dSmrg
4790e0b1094Smrg	    top    = (int)CEIL( glyphslot->metrics.horiBearingY );
4800e0b1094Smrg	    bottom = (int)FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
481c76ae52dSmrg	}
482c76ae52dSmrg
483c76ae52dSmrg	width = TRUNC(right - left);
484c76ae52dSmrg	height = TRUNC( top - bottom );
485c76ae52dSmrg
486c76ae52dSmrg	/*
487c76ae52dSmrg	 * Clip charcell glyphs to the bounding box
488c76ae52dSmrg	 * XXX transformed?
489c76ae52dSmrg	 */
490c76ae52dSmrg	if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
491c76ae52dSmrg	{
492c76ae52dSmrg	    if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
493c76ae52dSmrg	    {
494c76ae52dSmrg		if (TRUNC(bottom) > font->public.max_advance_width)
495c76ae52dSmrg		{
496c76ae52dSmrg		    int adjust;
4972836776bSmrg
498c76ae52dSmrg		    adjust = bottom - (font->public.max_advance_width << 6);
499c76ae52dSmrg		    if (adjust > top)
500c76ae52dSmrg			adjust = top;
501c76ae52dSmrg		    top -= adjust;
502c76ae52dSmrg		    bottom -= adjust;
503c76ae52dSmrg		    height = font->public.max_advance_width;
504c76ae52dSmrg		}
505c76ae52dSmrg	    }
506c76ae52dSmrg	    else
507c76ae52dSmrg	    {
508c76ae52dSmrg		if (TRUNC(right) > font->public.max_advance_width)
509c76ae52dSmrg		{
510c76ae52dSmrg		    int adjust;
5112836776bSmrg
512c76ae52dSmrg		    adjust = right - (font->public.max_advance_width << 6);
513c76ae52dSmrg		    if (adjust > left)
514c76ae52dSmrg			adjust = left;
515c76ae52dSmrg		    left -= adjust;
516c76ae52dSmrg		    right -= adjust;
517c76ae52dSmrg		    width = font->public.max_advance_width;
518c76ae52dSmrg		}
519c76ae52dSmrg	    }
520c76ae52dSmrg	}
521c76ae52dSmrg
5222836776bSmrg	if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
5232836776bSmrg	{
5242836776bSmrg	    error = FT_Render_Glyph( face->glyph, mode );
5252836776bSmrg	    if (error)
5262836776bSmrg		continue;
5272836776bSmrg	}
528c76ae52dSmrg
5292836776bSmrg	FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
530c76ae52dSmrg
531c76ae52dSmrg	if (font->info.spacing >= FC_MONO)
532c76ae52dSmrg	{
533c76ae52dSmrg	    if (font->info.transform)
534c76ae52dSmrg	    {
535c76ae52dSmrg		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
536c76ae52dSmrg		{
537c76ae52dSmrg		    vector.x = 0;
538c76ae52dSmrg		    vector.y = -face->size->metrics.max_advance;
539c76ae52dSmrg		}
540c76ae52dSmrg		else
541c76ae52dSmrg		{
542c76ae52dSmrg		    vector.x = face->size->metrics.max_advance;
543c76ae52dSmrg		    vector.y = 0;
544c76ae52dSmrg		}
545c76ae52dSmrg		FT_Vector_Transform (&vector, &font->info.matrix);
5460e0b1094Smrg		xftg->metrics.xOff = (short)(vector.x >> 6);
5470e0b1094Smrg		xftg->metrics.yOff = (short)(-(vector.y >> 6));
548c76ae52dSmrg	    }
549c76ae52dSmrg	    else
550c76ae52dSmrg	    {
551c76ae52dSmrg		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
552c76ae52dSmrg		{
553c76ae52dSmrg		    xftg->metrics.xOff = 0;
5540e0b1094Smrg		    xftg->metrics.yOff = (short)(-font->public.max_advance_width);
555c76ae52dSmrg		}
556c76ae52dSmrg		else
557c76ae52dSmrg		{
5580e0b1094Smrg		    xftg->metrics.xOff = (short)(font->public.max_advance_width);
559c76ae52dSmrg		    xftg->metrics.yOff = 0;
560c76ae52dSmrg		}
561c76ae52dSmrg	    }
562c76ae52dSmrg	}
563c76ae52dSmrg	else
564c76ae52dSmrg	{
5650e0b1094Smrg	    xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x)));
5660e0b1094Smrg	    xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
567c76ae52dSmrg	}
568c76ae52dSmrg
5690e0b1094Smrg	/* compute the size of the final bitmap */
5702836776bSmrg	ftbit = &glyphslot->bitmap;
571c76ae52dSmrg
5720e0b1094Smrg	width = (int)ftbit->width;
5730e0b1094Smrg	height = (int)ftbit->rows;
574c76ae52dSmrg
575c76ae52dSmrg	if (XftDebug() & XFT_DBG_GLYPH)
576c76ae52dSmrg	{
577c76ae52dSmrg	    printf ("glyph %d:\n", (int) glyphindex);
578c76ae52dSmrg	    printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n",
579c76ae52dSmrg		    (int) glyphslot->metrics.horiBearingX,
580c76ae52dSmrg		    (int) glyphslot->metrics.horiBearingY,
581c76ae52dSmrg		    (int) glyphslot->metrics.width,
582c76ae52dSmrg		    (int) glyphslot->metrics.height,
583c76ae52dSmrg		    left, right, top, bottom,
584c76ae52dSmrg		    width, height);
585c76ae52dSmrg	    if (XftDebug() & XFT_DBG_GLYPHV)
586c76ae52dSmrg	    {
587c76ae52dSmrg		int		x, y;
588c76ae52dSmrg		unsigned char	*line;
589c76ae52dSmrg
5902836776bSmrg		line = ftbit->buffer;
5912836776bSmrg		if (ftbit->pitch < 0)
5922836776bSmrg		    line -= ftbit->pitch*(height-1);
5932836776bSmrg
5942836776bSmrg		for (y = 0; y < height; y++)
595c76ae52dSmrg		{
5962836776bSmrg		    if (font->info.antialias)
597c76ae52dSmrg		    {
5982836776bSmrg			static const char    den[] = { " .:;=+*#" };
5992836776bSmrg			for (x = 0; x < width; x++)
600c76ae52dSmrg			    printf ("%c", den[line[x] >> 5]);
601c76ae52dSmrg		    }
602c76ae52dSmrg		    else
603c76ae52dSmrg		    {
6042836776bSmrg			for (x = 0; x < width * 8; x++)
605c76ae52dSmrg			{
606c76ae52dSmrg			    printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
607c76ae52dSmrg			}
608c76ae52dSmrg		    }
609c76ae52dSmrg		    printf ("|\n");
6102836776bSmrg		    line += ftbit->pitch;
611c76ae52dSmrg		}
612c76ae52dSmrg		printf ("\n");
613c76ae52dSmrg	    }
614c76ae52dSmrg	}
615c76ae52dSmrg
6162836776bSmrg	size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
6172836776bSmrg	if ( size < 0 )
6182836776bSmrg	    continue;
6192836776bSmrg
6200e0b1094Smrg	xftg->metrics.width  = (unsigned short)local.width;
6210e0b1094Smrg	xftg->metrics.height = (unsigned short)local.rows;
6220e0b1094Smrg	xftg->metrics.x      = (short)(- glyphslot->bitmap_left);
6230e0b1094Smrg	xftg->metrics.y      = (short)(  glyphslot->bitmap_top);
6242836776bSmrg
6252836776bSmrg	/*
6262836776bSmrg	 * If the glyph is relatively large (> 1% of server memory),
6272836776bSmrg	 * don't send it until necessary.
6282836776bSmrg	 */
6292836776bSmrg	if (!need_bitmaps && size > info->max_glyph_memory / 100)
6302836776bSmrg	    continue;
6312836776bSmrg
6322836776bSmrg	/*
6332836776bSmrg	 * Make sure there is enough buffer space for the glyph.
6342836776bSmrg	 */
6352836776bSmrg	if (size > bufSize)
6362836776bSmrg	{
6372836776bSmrg	    if (bufBitmap != bufLocal)
6382836776bSmrg		free (bufBitmap);
6390e0b1094Smrg	    bufBitmap = (unsigned char *) malloc ((size_t)size);
6402836776bSmrg	    if (!bufBitmap)
6412836776bSmrg		continue;
6422836776bSmrg	    bufSize = size;
6432836776bSmrg	}
6440e0b1094Smrg	memset (bufBitmap, 0, (size_t)size);
6452836776bSmrg
6462836776bSmrg	local.buffer = bufBitmap;
6472836776bSmrg
6482836776bSmrg	_fill_xrender_bitmap( &local, glyphslot, mode,
6492836776bSmrg			      (font->info.rgba == FC_RGBA_BGR ||
6502836776bSmrg			       font->info.rgba == FC_RGBA_VBGR ) );
6512836776bSmrg
6522836776bSmrg	/*
6532836776bSmrg	 * Copy or convert into local buffer.
6542836776bSmrg	 */
6552836776bSmrg
656c76ae52dSmrg	/*
657c76ae52dSmrg	 * Use the glyph index as the wire encoding; it
658c76ae52dSmrg	 * might be more efficient for some locales to map
659c76ae52dSmrg	 * these by first usage to smaller values, but that
660c76ae52dSmrg	 * would require persistently storing the map when
661c76ae52dSmrg	 * glyphs were freed.
662c76ae52dSmrg	 */
663c76ae52dSmrg	glyph = (Glyph) glyphindex;
664c76ae52dSmrg
6650e0b1094Smrg	xftg->glyph_memory = (size_t)size + sizeof (XftGlyph);
6662836776bSmrg	if (font->format)
667c76ae52dSmrg	{
6682836776bSmrg	    if (!font->glyphset)
6692836776bSmrg		font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
6702836776bSmrg	    if ( mode == FT_RENDER_MODE_MONO )
671c76ae52dSmrg	    {
6722836776bSmrg		/* swap bits in each byte */
6732836776bSmrg		if (BitmapBitOrder (dpy) != MSBFirst)
674c76ae52dSmrg		{
6752836776bSmrg		    unsigned char   *line = (unsigned char*)bufBitmap;
6762836776bSmrg		    int		    i = size;
6772836776bSmrg
6782836776bSmrg		    while (i--)
679c76ae52dSmrg		    {
6802836776bSmrg			int c = *line;
6812836776bSmrg			c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
6822836776bSmrg			c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
6832836776bSmrg			c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
6840e0b1094Smrg			*line++ = (unsigned char)c;
685c76ae52dSmrg		    }
686c76ae52dSmrg		}
687c76ae52dSmrg	    }
6882836776bSmrg	    else if ( mode != FT_RENDER_MODE_NORMAL )
689c76ae52dSmrg	    {
6902836776bSmrg		/* invert ARGB <=> BGRA */
691c76ae52dSmrg		if (ImageByteOrder (dpy) != XftNativeByteOrder ())
6922836776bSmrg		    XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
693c76ae52dSmrg	    }
6942836776bSmrg	    XRenderAddGlyphs (dpy, font->glyphset, &glyph,
6952836776bSmrg			      &xftg->metrics, 1,
6962836776bSmrg			      (char *) bufBitmap, size);
697c76ae52dSmrg	}
698c76ae52dSmrg	else
699c76ae52dSmrg	{
7002836776bSmrg	    if (size)
701c76ae52dSmrg	    {
7020e0b1094Smrg		xftg->bitmap = malloc ((size_t)size);
7032836776bSmrg		if (xftg->bitmap)
7040e0b1094Smrg		    memcpy (xftg->bitmap, bufBitmap, (size_t)size);
705c76ae52dSmrg	    }
706c76ae52dSmrg	    else
7072836776bSmrg		xftg->bitmap = NULL;
708c76ae52dSmrg	}
7092836776bSmrg
710c76ae52dSmrg	font->glyph_memory += xftg->glyph_memory;
711c76ae52dSmrg	info->glyph_memory += xftg->glyph_memory;
712c76ae52dSmrg	if (XftDebug() & XFT_DBG_CACHE)
713c76ae52dSmrg	    _XftFontValidateMemory (dpy, pub);
714c76ae52dSmrg	if (XftDebug() & XFT_DBG_CACHEV)
715c76ae52dSmrg	    printf ("Caching glyph 0x%x size %ld\n", glyphindex,
716c76ae52dSmrg		    xftg->glyph_memory);
717c76ae52dSmrg    }
718c76ae52dSmrg    if (bufBitmap != bufLocal)
719c76ae52dSmrg	free (bufBitmap);
720c76ae52dSmrg    XftUnlockFace (&font->public);
721c76ae52dSmrg}
722c76ae52dSmrg
723c76ae52dSmrg_X_EXPORT void
724c76ae52dSmrgXftFontUnloadGlyphs (Display		*dpy,
725c76ae52dSmrg		     XftFont		*pub,
726c76ae52dSmrg		     _Xconst FT_UInt	*glyphs,
727c76ae52dSmrg		     int		nglyph)
728c76ae52dSmrg{
729c76ae52dSmrg    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
730c76ae52dSmrg    XftFontInt	    *font = (XftFontInt *) pub;
731c76ae52dSmrg    XftGlyph	    *xftg;
732c76ae52dSmrg    FT_UInt	    glyphindex;
733c76ae52dSmrg    Glyph	    glyphBuf[1024];
734c76ae52dSmrg    int		    nused;
7352836776bSmrg
736c76ae52dSmrg    nused = 0;
737c76ae52dSmrg    while (nglyph--)
738c76ae52dSmrg    {
739c76ae52dSmrg	glyphindex = *glyphs++;
740c76ae52dSmrg	xftg = font->glyphs[glyphindex];
741c76ae52dSmrg	if (!xftg)
742c76ae52dSmrg	    continue;
743c76ae52dSmrg	if (xftg->glyph_memory)
744c76ae52dSmrg	{
745c76ae52dSmrg	    if (font->format)
746c76ae52dSmrg	    {
747c76ae52dSmrg		if (font->glyphset)
748c76ae52dSmrg		{
749c76ae52dSmrg		    glyphBuf[nused++] = (Glyph) glyphindex;
750c76ae52dSmrg		    if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
751c76ae52dSmrg		    {
752c76ae52dSmrg			XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
753c76ae52dSmrg			nused = 0;
754c76ae52dSmrg		    }
755c76ae52dSmrg		}
756c76ae52dSmrg	    }
757c76ae52dSmrg	    else
758c76ae52dSmrg	    {
759c76ae52dSmrg		if (xftg->bitmap)
760c76ae52dSmrg		    free (xftg->bitmap);
761c76ae52dSmrg	    }
762c76ae52dSmrg	    font->glyph_memory -= xftg->glyph_memory;
763c76ae52dSmrg	    if (info)
764c76ae52dSmrg		info->glyph_memory -= xftg->glyph_memory;
765c76ae52dSmrg	}
766c76ae52dSmrg	free (xftg);
767c76ae52dSmrg	XftMemFree (XFT_MEM_GLYPH, sizeof (XftGlyph));
7680d590c07Smrg	font->glyphs[glyphindex] = NULL;
7692836776bSmrg    }
770c76ae52dSmrg    if (font->glyphset && nused)
771c76ae52dSmrg	XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
772c76ae52dSmrg}
773c76ae52dSmrg
774c76ae52dSmrg_X_EXPORT FcBool
775c76ae52dSmrgXftFontCheckGlyph (Display	*dpy,
776c76ae52dSmrg		   XftFont	*pub,
777c76ae52dSmrg		   FcBool	need_bitmaps,
778c76ae52dSmrg		   FT_UInt	glyph,
779c76ae52dSmrg		   FT_UInt	*missing,
780c76ae52dSmrg		   int		*nmissing)
781c76ae52dSmrg{
782c76ae52dSmrg    XftFontInt	    *font = (XftFontInt *) pub;
783c76ae52dSmrg    XftGlyph	    *xftg;
784c76ae52dSmrg    int		    n;
7852836776bSmrg
786c76ae52dSmrg    if (glyph >= font->num_glyphs)
787c76ae52dSmrg	return FcFalse;
788c76ae52dSmrg    xftg = font->glyphs[glyph];
789c76ae52dSmrg    if (!xftg || (need_bitmaps && !xftg->glyph_memory))
790c76ae52dSmrg    {
791c76ae52dSmrg	if (!xftg)
792c76ae52dSmrg	{
793c76ae52dSmrg	    xftg = (XftGlyph *) malloc (sizeof (XftGlyph));
794c76ae52dSmrg	    if (!xftg)
795c76ae52dSmrg		return FcFalse;
796c76ae52dSmrg	    XftMemAlloc (XFT_MEM_GLYPH, sizeof (XftGlyph));
7970d590c07Smrg	    xftg->bitmap = NULL;
798c76ae52dSmrg	    xftg->glyph_memory = 0;
799c76ae52dSmrg	    font->glyphs[glyph] = xftg;
800c76ae52dSmrg	}
801c76ae52dSmrg	n = *nmissing;
802c76ae52dSmrg	missing[n++] = glyph;
803c76ae52dSmrg	if (n == XFT_NMISSING)
804c76ae52dSmrg	{
805c76ae52dSmrg	    XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
806c76ae52dSmrg	    n = 0;
807c76ae52dSmrg	}
808c76ae52dSmrg	*nmissing = n;
809c76ae52dSmrg	return FcTrue;
810c76ae52dSmrg    }
811c76ae52dSmrg    else
812c76ae52dSmrg	return FcFalse;
813c76ae52dSmrg}
814c76ae52dSmrg
815c76ae52dSmrg_X_EXPORT FcBool
816c76ae52dSmrgXftCharExists (Display	    *dpy,
817c76ae52dSmrg	       XftFont	    *pub,
818c76ae52dSmrg	       FcChar32    ucs4)
819c76ae52dSmrg{
820c76ae52dSmrg    if (pub->charset)
821c76ae52dSmrg	return FcCharSetHasChar (pub->charset, ucs4);
822c76ae52dSmrg    return FcFalse;
823c76ae52dSmrg}
824c76ae52dSmrg
825c76ae52dSmrg#define Missing	    ((FT_UInt) ~0)
826c76ae52dSmrg
827c76ae52dSmrg_X_EXPORT FT_UInt
8282836776bSmrgXftCharIndex (Display	    *dpy,
829c76ae52dSmrg	      XftFont	    *pub,
830c76ae52dSmrg	      FcChar32	    ucs4)
831c76ae52dSmrg{
832c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
833c76ae52dSmrg    FcChar32	ent, offset;
834c76ae52dSmrg    FT_Face	face;
8352836776bSmrg
836c76ae52dSmrg    if (!font->hash_value)
837c76ae52dSmrg	return 0;
838c76ae52dSmrg
8390e0b1094Smrg    ent = ucs4 % (FcChar32)font->hash_value;
840c76ae52dSmrg    offset = 0;
841c76ae52dSmrg    while (font->hash_table[ent].ucs4 != ucs4)
842c76ae52dSmrg    {
843c76ae52dSmrg	if (font->hash_table[ent].ucs4 == (FcChar32) ~0)
844c76ae52dSmrg	{
845c76ae52dSmrg	    if (!XftCharExists (dpy, pub, ucs4))
846c76ae52dSmrg		return 0;
847c76ae52dSmrg	    face  = XftLockFace (pub);
848c76ae52dSmrg	    if (!face)
849c76ae52dSmrg		return 0;
850c76ae52dSmrg	    font->hash_table[ent].ucs4 = ucs4;
851c76ae52dSmrg	    font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4);
852c76ae52dSmrg	    XftUnlockFace (pub);
853c76ae52dSmrg	    break;
854c76ae52dSmrg	}
855c76ae52dSmrg	if (!offset)
856c76ae52dSmrg	{
8570e0b1094Smrg	    offset = ucs4 % (FcChar32)font->rehash_value;
858c76ae52dSmrg	    if (!offset)
859c76ae52dSmrg		offset = 1;
860c76ae52dSmrg	}
861c76ae52dSmrg	ent = ent + offset;
862c76ae52dSmrg	if (ent >= font->hash_value)
8630e0b1094Smrg	    ent -= (FcChar32)font->hash_value;
864c76ae52dSmrg    }
865c76ae52dSmrg    return font->hash_table[ent].glyph;
866c76ae52dSmrg}
867c76ae52dSmrg
868c76ae52dSmrg/*
869c76ae52dSmrg * Pick a random glyph from the font and remove it from the cache
870c76ae52dSmrg */
871c76ae52dSmrg_X_HIDDEN void
872c76ae52dSmrg_XftFontUncacheGlyph (Display *dpy, XftFont *pub)
873c76ae52dSmrg{
874c76ae52dSmrg    XftFontInt	    *font = (XftFontInt *) pub;
875c76ae52dSmrg    unsigned long   glyph_memory;
876c76ae52dSmrg    FT_UInt	    glyphindex;
877c76ae52dSmrg    XftGlyph	    *xftg;
8782836776bSmrg
879c76ae52dSmrg    if (!font->glyph_memory)
880c76ae52dSmrg	return;
881c76ae52dSmrg    if (font->use_free_glyphs)
882c76ae52dSmrg    {
8830e0b1094Smrg	glyph_memory = ((unsigned long)rand() % font->glyph_memory);
884c76ae52dSmrg    }
885c76ae52dSmrg    else
886c76ae52dSmrg    {
887c76ae52dSmrg	if (font->glyphset)
888c76ae52dSmrg	{
889c76ae52dSmrg	    XRenderFreeGlyphSet (dpy, font->glyphset);
890c76ae52dSmrg	    font->glyphset = 0;
891c76ae52dSmrg	}
892c76ae52dSmrg	glyph_memory = 0;
893c76ae52dSmrg    }
8942836776bSmrg
895c76ae52dSmrg    if (XftDebug() & XFT_DBG_CACHE)
896c76ae52dSmrg	_XftFontValidateMemory (dpy, pub);
897c76ae52dSmrg    for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
898c76ae52dSmrg    {
899c76ae52dSmrg	xftg = font->glyphs[glyphindex];
900c76ae52dSmrg	if (xftg)
901c76ae52dSmrg	{
902c76ae52dSmrg	    if (xftg->glyph_memory > glyph_memory)
903c76ae52dSmrg	    {
904c76ae52dSmrg		if (XftDebug() & XFT_DBG_CACHEV)
905c76ae52dSmrg		    printf ("Uncaching glyph 0x%x size %ld\n",
906c76ae52dSmrg			    glyphindex, xftg->glyph_memory);
907c76ae52dSmrg		XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
908c76ae52dSmrg		if (!font->use_free_glyphs)
909c76ae52dSmrg		    continue;
910c76ae52dSmrg		break;
911c76ae52dSmrg	    }
912c76ae52dSmrg	    glyph_memory -= xftg->glyph_memory;
913c76ae52dSmrg	}
914c76ae52dSmrg    }
915c76ae52dSmrg    if (XftDebug() & XFT_DBG_CACHE)
916c76ae52dSmrg	_XftFontValidateMemory (dpy, pub);
917c76ae52dSmrg}
918c76ae52dSmrg
919c76ae52dSmrg_X_HIDDEN void
920c76ae52dSmrg_XftFontManageMemory (Display *dpy, XftFont *pub)
921c76ae52dSmrg{
922c76ae52dSmrg    XftFontInt	*font = (XftFontInt *) pub;
923c76ae52dSmrg
924c76ae52dSmrg    if (font->max_glyph_memory)
925c76ae52dSmrg    {
926c76ae52dSmrg	if (XftDebug() & XFT_DBG_CACHE)
927c76ae52dSmrg	{
928c76ae52dSmrg	    if (font->glyph_memory > font->max_glyph_memory)
929c76ae52dSmrg		printf ("Reduce memory for font 0x%lx from %ld to %ld\n",
930c76ae52dSmrg			font->glyphset ? font->glyphset : (unsigned long) font,
931c76ae52dSmrg			font->glyph_memory, font->max_glyph_memory);
932c76ae52dSmrg	}
933c76ae52dSmrg	while (font->glyph_memory > font->max_glyph_memory)
934c76ae52dSmrg	    _XftFontUncacheGlyph (dpy, pub);
935c76ae52dSmrg    }
936c76ae52dSmrg    _XftDisplayManageMemory (dpy);
937c76ae52dSmrg}
938