xftglyphs.c revision 8b1f82e3
1/*
2 * Copyright © 2022 Thomas E. Dickey
3 * Copyright © 2000 Keith Packard
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the above copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission.  The above copyright holders make no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO
16 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE
18 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "xftint.h"
25#include FT_OUTLINE_H
26#include FT_LCD_FILTER_H
27
28#include FT_SYNTHESIS_H
29
30#include FT_GLYPH_H
31
32typedef double m3x3[3][3];
33
34static void
35m3x3_uniform(m3x3 m)
36{
37    m[0][0] = m[1][1] = m[2][2] = 1.0;
38    m[0][1] = m[1][0] = m[0][2] = m[1][2] = m[2][0] = m[2][1] = 0;
39}
40
41static void
42m3x3_transform(FT_Vector *v, m3x3 m)
43{
44    double x, y;
45
46    x = (double)v->x;
47    y = (double)v->y;
48    v->x = (FT_Pos)(x * m[0][0] + y * m[0][1] + m[0][2] + 0.5);
49    v->y = (FT_Pos)(x * m[1][0] + y * m[1][1] + m[1][2] + 0.5);
50}
51
52static void
53m3x3_invert(m3x3 m, m3x3 mi)
54{
55    double det;
56
57    det  = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
58    det -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]);
59    det += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
60    det  = 1.0 / det;
61    mi[0][0] = det * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
62    mi[1][0] = det * (m[1][2] * m[2][0] - m[1][0] * m[2][2]);
63    mi[2][0] = det * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
64    mi[0][1] = det * (m[0][2] * m[2][1] - m[0][1] * m[2][2]);
65    mi[1][1] = det * (m[0][0] * m[2][2] - m[0][2] * m[2][0]);
66    mi[2][1] = det * (m[0][1] * m[2][0] - m[0][0] * m[2][1]);
67    mi[0][2] = det * (m[0][1] * m[1][2] - m[0][2] * m[1][1]);
68    mi[1][2] = det * (m[0][2] * m[1][0] - m[0][0] * m[1][2]);
69    mi[2][2] = det * (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
70}
71
72/*
73 * Validate the memory info for a font
74 */
75
76static void
77_XftFontValidateMemory (Display *dpy _X_UNUSED, XftFont *public)
78{
79    XftFontInt	    *font = (XftFontInt *) public;
80    unsigned long   glyph_memory;
81    FT_UInt	    glyphindex;
82    XftGlyph	    *xftg;
83
84    glyph_memory = 0;
85    for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
86    {
87	xftg = font->glyphs[glyphindex];
88	if (xftg)
89	{
90	    glyph_memory += xftg->glyph_memory;
91	}
92    }
93    if (glyph_memory != font->glyph_memory)
94	printf ("Font glyph cache incorrect has %lu bytes, should have %lu\n",
95		font->glyph_memory, glyph_memory);
96}
97
98/*
99 * Validate the glyph usage-links for a font.
100 */
101static void
102_XftValidateGlyphUsage(XftFontInt *font)
103{
104    if (font->newest != FT_UINT_MAX) {
105	FT_UInt forward;
106	FT_UInt reverse;
107	FT_UInt next;
108	XftGlyphUsage *x1st = (XftGlyphUsage *) font->glyphs[font->newest];
109	XftGlyphUsage *xuse = x1st;
110	for (forward = 1,
111	     next = x1st->newer;
112	     xuse != NULL &&
113	     next != font->newest;
114	     next = xuse->newer) {
115	    if (next >= font->num_glyphs) {
116		printf("Xft: out of range; %d\n", next);
117		break;
118	    }
119	    if (++forward > font->total_inuse) {
120		printf("Xft: too many in-use glyphs (%d vs %d)\n",
121		       forward, font->total_inuse);
122		if (forward > font->total_inuse + 10)
123		    break;
124	    }
125	    xuse = (XftGlyphUsage *) font->glyphs[next];
126	}
127	if (forward < font->total_inuse) {
128	    printf("Xft: too few in-use glyphs (%u vs %d)\n",
129		   forward, font->total_inuse);
130	}
131	for (reverse = 1,
132	     next = x1st->older;
133	     xuse != NULL &&
134	     next != font->newest;
135	     next = xuse->older) {
136	    if (next >= font->num_glyphs) {
137		printf("Xft out of range; %d\n", next);
138		break;
139	    }
140	    if (++reverse > font->total_inuse) {
141		printf("Xft: too many in-use glyphs (%d vs %d)\n",
142		       reverse, font->total_inuse);
143		if (reverse > font->total_inuse + 10)
144		    break;
145	    }
146	    xuse = (XftGlyphUsage *) font->glyphs[next];
147	}
148	if (reverse < font->total_inuse) {
149	    printf("Xft: too few in-use glyphs (%u vs %d)\n",
150		   reverse, font->total_inuse);
151	}
152	if (forward != reverse) {
153	    printf("Xft: forward %d vs reverse %d\n",
154		   forward, reverse);
155	    exit(1);
156	}
157    }
158}
159
160/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
161 * into a different format. For example, we want to convert a
162 * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
163 * ARGB or ABGR bitmap.
164 *
165 * this function prepares a target descriptor for this operation.
166 *
167 * input :: target bitmap descriptor. The function will set its
168 *          'width', 'rows' and 'pitch' fields, and only these
169 *
170 * slot  :: the glyph slot containing the source bitmap. this
171 *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
172 *
173 * mode  :: the requested final rendering mode. supported values are
174 *          MONO, NORMAL (i.e. gray), LCD and LCD_V
175 *
176 * the function returns the size in bytes of the corresponding buffer,
177 * it's up to the caller to allocate the corresponding memory block
178 * before calling _fill_xrender_bitmap
179 *
180 * it also returns -1 in case of error (e.g. incompatible arguments,
181 * like trying to convert a gray bitmap into a monochrome one)
182 */
183static int
184_compute_xrender_bitmap_size( FT_Bitmap*	target,
185			      FT_GlyphSlot	slot,
186			      FT_Render_Mode	mode,
187			      FT_Matrix*	matrix,
188			      m3x3		m )
189{
190    FT_Bitmap*	ftbit;
191    int		width, height, pitch;
192
193    if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
194	return -1;
195
196    /* compute the size of the final bitmap */
197    ftbit = &slot->bitmap;
198
199    width = (int)ftbit->width;
200    height = (int)ftbit->rows;
201
202    if ( matrix && mode == FT_RENDER_MODE_NORMAL )
203    {
204	FT_Matrix mirror, inverse;
205	FT_Vector vector;
206	int xc, yc;
207	int left, right, top, bottom;
208
209	left = right = top = bottom = 0;
210	for (xc = 0; xc <= 1; xc++) {
211	    for (yc = 0; yc <= 1; yc++) {
212		vector.x = xc * width;
213		vector.y = yc * height;
214		FT_Vector_Transform(&vector, matrix);
215		if (xc == 0 && yc == 0) {
216		    left = right = (int)vector.x;
217		    top = bottom = (int)vector.y;
218		} else {
219		    if (left   > vector.x) left   = (int)vector.x;
220		    if (right  < vector.x) right  = (int)vector.x;
221		    if (bottom > vector.y) bottom = (int)vector.y;
222		    if (top    < vector.y) top    = (int)vector.y;
223		}
224	    }
225	}
226	width = (int)(right - left);
227	height = (int)(top - bottom);
228
229	mirror.xx = + 0x10000;
230	mirror.yy = - 0x10000;
231	mirror.xy = mirror.yx = 0;
232	inverse = *matrix;
233	FT_Matrix_Multiply(&mirror, &inverse);
234	FT_Matrix_Invert(&inverse);
235	FT_Matrix_Multiply(&mirror, &inverse);
236
237	vector.x = vector.y = 0;
238	FT_Vector_Transform(&vector, &inverse);
239	left = (int)vector.x;
240	bottom = (int)vector.y;
241	vector.x = width;
242	vector.y = height;
243	FT_Vector_Transform(&vector, &inverse);
244	right = (int)vector.x;
245	top = (int)vector.y;
246	left = (right - left) - (int)ftbit->width;
247	bottom = (top - bottom) - (int)ftbit->rows;
248
249	m[0][0] = (double)inverse.xx / 0x10000;
250	m[0][1] = (double)inverse.xy / 0x10000;
251	m[1][0] = (double)inverse.yx / 0x10000;
252	m[1][1] = (double)inverse.yy / 0x10000;
253	m[0][2] = (double)-left / 2;
254	m[1][2] = (double)-bottom / 2;
255	m[2][0] = m[2][1] = 0.0;
256	m[2][2] = 1.0;
257    }
258    pitch = (width+3) & ~3;
259
260    switch ( ftbit->pixel_mode )
261    {
262    case FT_PIXEL_MODE_MONO:
263	if ( mode == FT_RENDER_MODE_MONO )
264	{
265	    pitch = (((width+31) & ~31) >> 3);
266	    break;
267	}
268	/* fall-through */
269
270    case FT_PIXEL_MODE_GRAY:
271	if ( mode == FT_RENDER_MODE_LCD ||
272	     mode == FT_RENDER_MODE_LCD_V )
273	{
274	    /* each pixel is replicated into a 32-bit ARGB value */
275	    pitch = width*4;
276	}
277	break;
278
279    case FT_PIXEL_MODE_BGRA:
280	pitch = width * 4;
281	break;
282
283    case FT_PIXEL_MODE_LCD:
284	if ( mode != FT_RENDER_MODE_LCD )
285	    return -1;
286
287	/* horz pixel triplets are packed into 32-bit ARGB values */
288	width /= 3;
289	pitch = width*4;
290	break;
291
292    case FT_PIXEL_MODE_LCD_V:
293	if ( mode != FT_RENDER_MODE_LCD_V )
294	    return -1;
295
296	/* vert pixel triplets are packed into 32-bit ARGB values */
297	height /= 3;
298	pitch = width*4;
299	break;
300
301    default:  /* unsupported source format */
302	return -1;
303    }
304
305    target->width = (unsigned)width;
306    target->rows = (unsigned)height;
307    target->pitch = pitch;
308    target->buffer = NULL;
309
310    return pitch * height;
311}
312
313/* this functions converts the glyph bitmap found in a FT_GlyphSlot
314 * into a different format while scaling by applying the given matrix
315 * (see _compute_xrender_bitmap_size)
316 *
317 * you should call this function after _compute_xrender_bitmap_size
318 *
319 * target :: target bitmap descriptor. Note that its 'buffer' pointer
320 *           must point to memory allocated by the caller
321 *
322 * source :: the source bitmap descriptor
323 *
324 * matrix :: the scaling matrix to apply
325 */
326static void
327_scaled_fill_xrender_bitmap( FT_Bitmap*	target,
328			     FT_Bitmap* source,
329			     m3x3 m )
330{
331    unsigned char*	src_buf	  = source->buffer;
332    unsigned char*	dst_line  = target->buffer;
333    int			src_pitch = source->pitch;
334    int			width     = (int) target->width;
335    int			height    = (int) target->rows;
336    int			pitch     = target->pitch;
337    int			i, x, y;
338    FT_Vector		vector, vector0;
339    int			sampling_width;
340    int			sampling_height;
341    int			sample_count;
342
343    if ( src_pitch < 0 )
344	src_buf -= ((unsigned) src_pitch * (source->rows - 1));
345
346    /* compute how many source pixels a target pixel spans */
347    vector.x = 1;
348    vector.y = 1;
349    m3x3_transform(&vector, m);
350    vector0.x = 0;
351    vector0.y = 0;
352    m3x3_transform(&vector0, m);
353    sampling_width = (int) ((vector.x - vector0.x) / 2);
354    sampling_height = (int) ((vector.y - vector0.y) / 2);
355    if (sampling_width < 0) sampling_width = -sampling_width;
356    if (sampling_height < 0) sampling_height = -sampling_height;
357    sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1);
358
359    for	( y = height; y > 0; y--, dst_line += pitch )
360    {
361	for ( x	= 0; x < width; x++ )
362	{
363	    unsigned char* src;
364
365	    /* compute target pixel location in source space */
366	    vector.x = x;
367	    vector.y = height - y;
368	    m3x3_transform(&vector, m);
369
370	    if (source->pixel_mode == FT_PIXEL_MODE_BGRA)
371	    {
372		if (vector.x < -sampling_width
373		 || vector.x > (source->width + (unsigned) sampling_width))
374		    continue;
375		if (vector.y < -sampling_height
376		 || vector.y > (source->rows + (unsigned) sampling_height))
377		    continue;
378	    }
379	    else
380	    {
381		if (vector.x < 0 || vector.x >= source->width)
382		    continue;
383		if (vector.y < 0 || vector.y >= source->rows)
384		    continue;
385	    }
386
387	    switch ( source->pixel_mode )
388	    {
389	    case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */
390		src = src_buf + (vector.y * src_pitch);
391		if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) )
392		    dst_line[x] = 0xff;
393		break;
394
395	    case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */
396		src = src_buf + (vector.y * src_pitch);
397		dst_line[x] = src[vector.x];
398		break;
399
400	    case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */
401	    {
402		int sample_x, sample_y;
403		int bgra[4] = { 0, 0, 0, 0 };
404
405		for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y)
406		{
407		    int src_y = (int) (vector.y + sample_y);
408
409		    if (src_y < 0 || (FT_Pos) src_y >= source->rows)
410			continue;
411		    src = src_buf + (src_y * src_pitch);
412		    for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x)
413		    {
414			int src_x = (int) (vector.x + sample_x);
415
416			if (src_x < 0 || (FT_Pos) src_x >= source->width)
417			    continue;
418			for (i = 0; i < 4; ++i)
419			    bgra[i] += src[src_x * 4 + i];
420		    }
421		}
422
423		for (i = 0; i < 4; ++i)
424		    dst_line[4 * x + i] = (unsigned char) (bgra[i] / sample_count);
425		break;
426	    }
427	    }
428	}
429    }
430}
431
432/* this functions converts the glyph bitmap found in a FT_GlyphSlot
433 * into a different format (see _compute_xrender_bitmap_size)
434 *
435 * you should call this function after _compute_xrender_bitmap_size
436 *
437 * target :: target bitmap descriptor. Note that its 'buffer' pointer
438 *           must point to memory allocated by the caller
439 *
440 * slot   :: the glyph slot containing the source bitmap
441 *
442 * mode   :: the requested final rendering mode
443 *
444 * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
445 */
446static void
447_fill_xrender_bitmap( FT_Bitmap*	target,
448		      FT_GlyphSlot	slot,
449		      FT_Render_Mode	mode,
450		      int		bgr )
451{
452    FT_Bitmap*   ftbit = &slot->bitmap;
453
454    {
455	unsigned char*	srcLine	= ftbit->buffer;
456	unsigned char*	dstLine	= target->buffer;
457	int		src_pitch = ftbit->pitch;
458	int		width = (int)target->width;
459	int		height = (int)target->rows;
460	int		pitch = target->pitch;
461	int		subpixel;
462	int		h;
463
464	subpixel = ( mode == FT_RENDER_MODE_LCD ||
465		     mode == FT_RENDER_MODE_LCD_V );
466
467	if ( src_pitch < 0 )
468	    srcLine -= ((unsigned)src_pitch * (ftbit->rows-1));
469
470	switch ( ftbit->pixel_mode )
471	{
472	case FT_PIXEL_MODE_MONO:
473	    if ( subpixel )  /* convert mono to ARGB32 values */
474	    {
475		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
476		{
477		    int x;
478
479		    for ( x = 0; x < width; x++ )
480		    {
481			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
482			    ((unsigned int*)dstLine)[x] = 0xffffffffU;
483		    }
484		}
485	    }
486	    else if ( mode == FT_RENDER_MODE_NORMAL )  /* convert mono to 8-bit gray */
487	    {
488		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
489		{
490		    int x;
491
492		    for ( x = 0; x < width; x++ )
493		    {
494			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
495			    dstLine[x] = 0xff;
496		    }
497		}
498	    }
499	    else  /* copy mono to mono */
500	    {
501		int bytes = (width+7) >> 3;
502
503		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
504		    memcpy( dstLine, srcLine, (size_t)bytes );
505	    }
506	    break;
507
508	case FT_PIXEL_MODE_GRAY:
509	    if ( subpixel )  /* convert gray to ARGB32 values */
510	    {
511		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
512		{
513		    int		   x;
514		    unsigned int*  dst = (unsigned int*)dstLine;
515
516		    for ( x = 0; x < width; x++ )
517		    {
518			unsigned int pix = srcLine[x];
519
520			pix |= (pix << 8);
521			pix |= (pix << 16);
522
523			dst[x] = pix;
524		    }
525		}
526	    }
527	    else  /* copy gray into gray */
528	    {
529		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
530		    memcpy( dstLine, srcLine, (size_t)width );
531	    }
532	    break;
533
534	case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */
535	    for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
536		memcpy( dstLine, srcLine, (size_t) width * 4 );
537	    break;
538
539	case FT_PIXEL_MODE_LCD:
540	    if ( !bgr )
541	    {
542		/* convert horizontal RGB into ARGB32 */
543		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
544		{
545		    int		   x;
546		    unsigned char* src = srcLine;
547		    unsigned int*  dst = (unsigned int*)dstLine;
548
549		    for ( x = 0; x < width; x++, src += 3 )
550		    {
551			unsigned int pix;
552
553			pix = ((unsigned int)src[0] << 16) |
554			      ((unsigned int)src[1] <<  8) |
555			      ((unsigned int)src[2]      ) |
556			      ((unsigned int)src[1] << 24) ;
557
558			dst[x] = pix;
559		    }
560		}
561	    }
562	    else
563	    {
564		/* convert horizontal BGR into ARGB32 */
565		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
566		{
567		    int		   x;
568		    unsigned char* src = srcLine;
569		    unsigned int*  dst = (unsigned int*)dstLine;
570
571		    for ( x = 0; x < width; x++, src += 3 )
572		    {
573			unsigned int pix;
574
575			pix = ((unsigned int)src[2] << 16) |
576			      ((unsigned int)src[1] <<  8) |
577			      ((unsigned int)src[0]      ) |
578			      ((unsigned int)src[1] << 24) ;
579
580			dst[x] = pix;
581		    }
582		}
583	    }
584	    break;
585
586	default:  /* FT_PIXEL_MODE_LCD_V */
587	    /* convert vertical RGB into ARGB32 */
588	    if ( !bgr )
589	    {
590		for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
591		{
592		    int		   x;
593		    unsigned char* src = srcLine;
594		    unsigned int*  dst = (unsigned int*)dstLine;
595
596		    for ( x = 0; x < width; x++, src += 1 )
597		    {
598			unsigned int  pix;
599
600			pix = ((unsigned int)src[0]           << 16) |
601			      ((unsigned int)src[src_pitch]   <<  8) |
602			      ((unsigned int)src[src_pitch*2]      ) |
603			      ((unsigned int)src[src_pitch]   << 24) ;
604
605			dst[x] = pix;
606		    }
607		}
608	    }
609	    else
610	    {
611	    for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
612		{
613		    int		   x;
614		    unsigned char* src = srcLine;
615		    unsigned int*  dst = (unsigned int*)dstLine;
616
617		    for ( x = 0; x < width; x++, src += 1 )
618		    {
619			unsigned int  pix;
620
621			pix = ((unsigned int)src[src_pitch*2] << 16) |
622			      ((unsigned int)src[src_pitch]   <<  8) |
623			      ((unsigned int)src[0]                ) |
624			      ((unsigned int)src[src_pitch]   << 24) ;
625
626			dst[x] = pix;
627		    }
628		}
629	    }
630	}
631    }
632}
633
634_X_EXPORT void
635XftFontLoadGlyphs (Display	    *dpy,
636		   XftFont	    *pub,
637		   FcBool	    need_bitmaps,
638		   _Xconst FT_UInt  *glyphs,
639		   int		    nglyph)
640{
641    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
642    XftFontInt	    *font = (XftFontInt *) pub;
643    FT_Error	    error;
644    FT_UInt	    glyphindex;
645    FT_GlyphSlot    glyphslot;
646    XftGlyph	    *xftg;
647    Glyph	    glyph;
648    unsigned char   bufLocal[4096];
649    unsigned char   *bufBitmap = bufLocal;
650    int		    bufSize = sizeof (bufLocal);
651    int		    size;
652    int		    width;
653    int		    height;
654    int		    left, right, top, bottom;
655    FT_Bitmap*	    ftbit;
656    FT_Bitmap	    local;
657    FT_Vector	    vector;
658    m3x3	    m;
659    FT_Face	    face;
660    FT_Render_Mode  mode = FT_RENDER_MODE_MONO;
661    FcBool	    transform;
662    FcBool	    glyph_transform;
663
664    if (!info)
665	return;
666
667    face = XftLockFace (&font->public);
668
669    if (!face)
670	return;
671
672    if (font->info.color)
673	mode = FT_RENDER_MODE_NORMAL;
674    if (font->info.antialias)
675    {
676	switch (font->info.rgba) {
677	case FC_RGBA_RGB:
678	case FC_RGBA_BGR:
679	    mode = FT_RENDER_MODE_LCD;
680	    break;
681	case FC_RGBA_VRGB:
682	case FC_RGBA_VBGR:
683	    mode = FT_RENDER_MODE_LCD_V;
684	    break;
685	default:
686	    mode = FT_RENDER_MODE_NORMAL;
687	}
688    }
689
690    transform = font->info.transform && mode != FT_RENDER_MODE_MONO;
691
692    while (nglyph--)
693    {
694	glyphindex = *glyphs++;
695	xftg = font->glyphs[glyphindex];
696	if (!xftg)
697	    continue;
698
699	if (XftDebug() & XFT_DBG_CACHE)
700	    _XftFontValidateMemory (dpy, pub);
701	/*
702	 * Check to see if this glyph has just been loaded,
703	 * this happens when drawing the same glyph twice
704	 * in a single string
705	 */
706	if (xftg->glyph_memory)
707	    continue;
708
709	FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter);
710
711	error = FT_Load_Glyph (face, glyphindex, font->info.load_flags);
712	if (error)
713	{
714	    /*
715	     * If anti-aliasing or transforming glyphs and
716	     * no outline version exists, fallback to the
717	     * bitmap and let things look bad instead of
718	     * missing the glyph
719	     */
720	    if (font->info.load_flags & FT_LOAD_NO_BITMAP)
721		error = FT_Load_Glyph (face, glyphindex,
722				       font->info.load_flags & ~FT_LOAD_NO_BITMAP);
723	    if (error)
724		continue;
725	}
726
727#define FLOOR(x)    ((x) & -64)
728#define CEIL(x)	    (((x)+63) & -64)
729#define TRUNC(x)    ((x) >> 6)
730#define ROUND(x)    (((x)+32) & -64)
731
732	glyphslot = face->glyph;
733
734	/*
735	 * Embolden if required
736	 */
737	if (font->info.embolden) FT_GlyphSlot_Embolden(glyphslot);
738
739	/*
740	 * Compute glyph metrics from FreeType information
741	 */
742	if (transform)
743	{
744	    /*
745	     * calculate the true width by transforming all four corners.
746	     */
747	    int xc, yc;
748	    left = right = top = bottom = 0;
749	    for (xc = 0; xc <= 1; xc++) {
750		for (yc = 0; yc <= 1; yc++) {
751		    vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width;
752		    vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height;
753		    FT_Vector_Transform(&vector, &font->info.matrix);
754		    if (XftDebug() & XFT_DBG_GLYPH)
755			printf("Trans %d %d: %d %d\n", (int) xc, (int) yc,
756			       (int) vector.x, (int) vector.y);
757		    if (xc == 0 && yc == 0) {
758			left = right = (int)vector.x;
759			top = bottom = (int)vector.y;
760		    } else {
761			if (left   > vector.x) left   = (int)vector.x;
762			if (right  < vector.x) right  = (int)vector.x;
763			if (bottom > vector.y) bottom = (int)vector.y;
764			if (top	   < vector.y) top    = (int)vector.y;
765		    }
766
767		}
768	    }
769	    left   = (int)FLOOR(left);
770	    right  = (int)CEIL(right);
771	    bottom = (int)FLOOR(bottom);
772	    top	   = (int)CEIL(top);
773
774	} else {
775	    left   = (int)FLOOR( glyphslot->metrics.horiBearingX );
776	    right  = (int)CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width );
777
778	    top    = (int)CEIL( glyphslot->metrics.horiBearingY );
779	    bottom = (int)FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
780	}
781
782	/*
783	 * Clip charcell glyphs to the bounding box
784	 * XXX transformed?
785	 */
786	if (font->info.spacing >= FC_CHARCELL && !transform)
787	{
788	    if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
789	    {
790		if (TRUNC(bottom) > font->public.max_advance_width)
791		{
792		    int adjust;
793
794		    adjust = bottom - (font->public.max_advance_width << 6);
795		    if (adjust > top)
796			adjust = top;
797		    top -= adjust;
798		    bottom -= adjust;
799		}
800	    }
801	    else
802	    {
803		if (TRUNC(right) > font->public.max_advance_width)
804		{
805		    int adjust;
806
807		    adjust = right - (font->public.max_advance_width << 6);
808		    if (adjust > left)
809			adjust = left;
810		    left -= adjust;
811		    right -= adjust;
812		}
813	    }
814	}
815
816	glyph_transform = transform;
817	if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
818	{
819	    error = FT_Render_Glyph( face->glyph, mode );
820	    if (error)
821		continue;
822	    glyph_transform = False;
823	}
824
825	FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
826
827	if (font->info.spacing >= FC_MONO)
828	{
829	    if (transform)
830	    {
831		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
832		{
833		    vector.x = 0;
834		    vector.y = -face->size->metrics.max_advance;
835		}
836		else
837		{
838		    vector.x = face->size->metrics.max_advance;
839		    vector.y = 0;
840		}
841		FT_Vector_Transform(&vector, &font->info.matrix);
842		xftg->metrics.xOff = (short)(TRUNC(ROUND(vector.x)));
843		xftg->metrics.yOff = (short)(TRUNC(ROUND(vector.y)));
844	    }
845	    else
846	    {
847		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
848		{
849		    xftg->metrics.xOff = 0;
850		    xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
851		}
852		else
853		{
854		    xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x)));
855		    xftg->metrics.yOff = 0;
856		}
857	    }
858	}
859	else
860	{
861	    xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x)));
862	    xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
863	}
864
865	/* compute the size of the final bitmap */
866	ftbit = &glyphslot->bitmap;
867
868	width = (int)ftbit->width;
869	height = (int)ftbit->rows;
870
871	if (XftDebug() & XFT_DBG_GLYPH)
872	{
873	    printf ("glyph %d:\n", (int) glyphindex);
874	    printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n",
875		    (int) glyphslot->metrics.horiBearingX,
876		    (int) glyphslot->metrics.horiBearingY,
877		    (int) glyphslot->metrics.width,
878		    (int) glyphslot->metrics.height,
879		    left, right, top, bottom,
880		    width, height);
881	    if (XftDebug() & XFT_DBG_GLYPHV)
882	    {
883		int		x, y;
884		unsigned char	*line;
885
886		line = ftbit->buffer;
887		if (ftbit->pitch < 0)
888		    line -= ftbit->pitch*(height-1);
889
890		for (y = 0; y < height; y++)
891		{
892		    if (font->info.antialias)
893		    {
894			static const char    den[] = { " .:;=+*#" };
895			for (x = 0; x < width; x++)
896			    printf ("%c", den[line[x] >> 5]);
897		    }
898		    else
899		    {
900			for (x = 0; x < width * 8; x++)
901			{
902			    printf ("%c", (line[x>>3] & (1 << (x & 7))) ? '#' : ' ');
903			}
904		    }
905		    printf ("|\n");
906		    line += ftbit->pitch;
907		}
908		printf ("\n");
909	    }
910	}
911
912	m3x3_uniform(m);
913	size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL, m );
914	if ( size < 0 )
915	    continue;
916
917	xftg->metrics.width  = (unsigned short)local.width;
918	xftg->metrics.height = (unsigned short)local.rows;
919	if (glyph_transform)
920	{
921	    m3x3 mi;
922
923	    m3x3_invert(m, mi);
924	    vector.x = - glyphslot->bitmap_left;
925	    vector.y =   glyphslot->bitmap_top;
926	    m3x3_transform(&vector, mi);
927	    xftg->metrics.x = (short)vector.x;
928	    xftg->metrics.y = (short)vector.y;
929	}
930	else
931	{
932	    xftg->metrics.x = (short)(- glyphslot->bitmap_left);
933	    xftg->metrics.y = (short)(  glyphslot->bitmap_top);
934	}
935
936	/*
937	 * If the glyph is relatively large (> 1% of server memory),
938	 * don't send it until necessary.
939	 */
940	if (!need_bitmaps && ((unsigned long) size > (info->max_glyph_memory / 100)))
941	    continue;
942
943	/*
944	 * Make sure there is enough buffer space for the glyph.
945	 */
946	if (size > bufSize)
947	{
948	    if (bufBitmap != bufLocal)
949		free (bufBitmap);
950	    bufBitmap = (unsigned char *) malloc ((size_t)size);
951	    if (!bufBitmap)
952		continue;
953	    bufSize = size;
954	}
955	memset (bufBitmap, 0, (size_t)size);
956
957	local.buffer = bufBitmap;
958
959	if (mode == FT_RENDER_MODE_NORMAL && glyph_transform)
960	    _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, m);
961	else
962	    _fill_xrender_bitmap( &local, glyphslot, mode,
963				 (font->info.rgba == FC_RGBA_BGR ||
964				  font->info.rgba == FC_RGBA_VBGR) );
965
966	/*
967	 * Copy or convert into local buffer.
968	 */
969
970	/*
971	 * Use the glyph index as the wire encoding; it
972	 * might be more efficient for some locales to map
973	 * these by first usage to smaller values, but that
974	 * would require persistently storing the map when
975	 * glyphs were freed.
976	 */
977	glyph = (Glyph) glyphindex;
978
979	if (xftg->picture)
980	{
981	    XRenderFreePicture(dpy, xftg->picture);
982	    xftg->picture = 0;
983	}
984	xftg->glyph_memory = (size_t)size + font->sizeof_glyph;
985	if (font->format)
986	{
987	    if (!font->glyphset)
988		font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
989	    if ( mode == FT_RENDER_MODE_MONO )
990	    {
991		/* swap bits in each byte */
992		if (BitmapBitOrder (dpy) != MSBFirst)
993		{
994		    unsigned char   *line = (unsigned char*)bufBitmap;
995		    int		    i = size;
996
997		    while (i--)
998		    {
999			int c = *line;
1000			c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
1001			c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
1002			c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
1003			*line++ = (unsigned char)c;
1004		    }
1005		}
1006	    }
1007	    else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL)
1008	    {
1009		/* invert ARGB <=> BGRA */
1010		if (ImageByteOrder (dpy) != XftNativeByteOrder ())
1011		    XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
1012	    }
1013
1014	    if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
1015	    {
1016		Pixmap pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), local.width, local.rows, 32);
1017		GC gc = XCreateGC(dpy, pixmap, 0, NULL);
1018		XImage image = {
1019		    (int) local.width, (int) local.rows, 0, ZPixmap, (char *)bufBitmap,
1020		    dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32,
1021		    32, (int) (local.width * 4 - (unsigned) local.pitch), 32,
1022		    0, 0, 0, NULL, { NULL }
1023		};
1024
1025		XInitImage(&image);
1026		XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, local.width, local.rows);
1027		xftg->picture = XRenderCreatePicture(dpy, pixmap, font->format, 0, NULL);
1028
1029		XFreeGC(dpy, gc);
1030		XFreePixmap(dpy, pixmap);
1031		/*
1032		 * Record 256 times higher memory pressure for unrotated
1033		 * pictures, and maximum for rotated pictures.
1034		 */
1035		if (font->info.matrix.xy || font->info.matrix.yx)
1036		    xftg->glyph_memory += font->max_glyph_memory - (unsigned long) size;
1037		else
1038		    xftg->glyph_memory += (size_t)size * 255;
1039	    }
1040	    else
1041		XRenderAddGlyphs (dpy, font->glyphset, &glyph,
1042				  &xftg->metrics, 1,
1043				  (char *) bufBitmap, size);
1044	}
1045	else
1046	{
1047	    if (size)
1048	    {
1049		xftg->bitmap = malloc ((size_t)size);
1050		if (xftg->bitmap)
1051		    memcpy (xftg->bitmap, bufBitmap, (size_t)size);
1052	    }
1053	    else
1054		xftg->bitmap = NULL;
1055	}
1056
1057	font->glyph_memory += xftg->glyph_memory;
1058	info->glyph_memory += xftg->glyph_memory;
1059	if (XftDebug() & XFT_DBG_CACHE)
1060	    _XftFontValidateMemory (dpy, pub);
1061	if (XftDebug() & XFT_DBG_CACHEV)
1062	    printf ("Caching glyph 0x%x size %lu\n", glyphindex,
1063		    xftg->glyph_memory);
1064
1065	if (font->track_mem_usage) {
1066	    XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
1067
1068	    if (font->newest == FT_UINT_MAX) {
1069		xuse->older = glyphindex;
1070	        xuse->newer = glyphindex;
1071		if (XftDebug() & XFT_DBG_USAGE)
1072		    printf("alloc %p -> %d: %p USE %d.%d\n",
1073			    (void *) font, glyphindex,
1074			    (void *) xuse, xuse->older, xuse->newer);
1075	    } else {
1076		XftGlyphUsage *xnew;
1077		XftGlyphUsage *xold;
1078
1079		assert(font->glyphs[font->newest] != NULL);
1080		xnew = (XftGlyphUsage *) font->glyphs[font->newest];
1081
1082		assert(font->glyphs[xnew->newer] != NULL);
1083		xold = (XftGlyphUsage *) font->glyphs[xnew->newer];
1084
1085		xuse->older = font->newest;
1086		xuse->newer = xnew->newer;
1087		xnew->newer = glyphindex;
1088		xold->older = glyphindex;
1089		if (XftDebug() & XFT_DBG_USAGE)
1090		    printf("alloc %p -> %d: %p USE %d.%d, %p NEW %d.%d %p OLD %d.%d\n",
1091			    (void *) font, glyphindex,
1092			    (void *) xuse, xuse->older, xuse->newer,
1093			    (void *) xnew, xnew->older, xnew->newer,
1094			    (void *) xold, xold->older, xold->newer);
1095	    }
1096
1097	    font->newest = glyphindex;
1098	    font->total_inuse++;
1099	    if (XftDebug() & XFT_DBG_USAGE)
1100		_XftValidateGlyphUsage(font);
1101	}
1102    }
1103    if (bufBitmap != bufLocal)
1104	free (bufBitmap);
1105    XftUnlockFace (&font->public);
1106}
1107
1108_X_EXPORT void
1109XftFontUnloadGlyphs (Display		*dpy,
1110		     XftFont		*pub,
1111		     _Xconst FT_UInt	*glyphs,
1112		     int		nglyph)
1113{
1114    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
1115    XftFontInt	    *font = (XftFontInt *) pub;
1116    XftGlyph	    *xftg;
1117    FT_UInt	    glyphindex;
1118    Glyph	    glyphBuf[1024];
1119    int		    nused;
1120
1121    nused = 0;
1122    while (nglyph--)
1123    {
1124	glyphindex = *glyphs++;
1125	xftg = font->glyphs[glyphindex];
1126	if (!xftg)
1127	    continue;
1128	if (xftg->glyph_memory)
1129	{
1130	    if (XftDebug() & XFT_DBG_CACHEV)
1131		printf ("Uncaching glyph 0x%x size %lu\n",
1132			glyphindex, xftg->glyph_memory);
1133	    if (font->format)
1134	    {
1135		if (xftg->picture)
1136		    XRenderFreePicture(dpy, xftg->picture);
1137		else if (font->glyphset)
1138		{
1139		    glyphBuf[nused++] = (Glyph) glyphindex;
1140		    if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
1141		    {
1142			XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
1143			nused = 0;
1144		    }
1145		}
1146	    }
1147	    else if (xftg->bitmap)
1148		free (xftg->bitmap);
1149	    font->glyph_memory -= xftg->glyph_memory;
1150	    if (info)
1151		info->glyph_memory -= xftg->glyph_memory;
1152	}
1153
1154	if (font->track_mem_usage) {
1155	    XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
1156	    XftGlyphUsage *xtmp;
1157
1158	    if (XftDebug() & XFT_DBG_USAGE)
1159		printf("free %p -> %p USE %d.%d\n",
1160		       (void *) font, (void *) xuse, xuse->older, xuse->newer);
1161
1162	    if (xuse->older != FT_UINT_MAX) {
1163		xtmp = (XftGlyphUsage *) font->glyphs[xuse->older];
1164		if (xtmp != NULL) {
1165		    /* update link around to oldest glyph */
1166		    xtmp->newer = xuse->newer;
1167		}
1168		if (font->newest == glyphindex) {
1169		    if (font->newest == xuse->older)
1170			font->newest = FT_UINT_MAX;
1171		    else
1172			font->newest = xuse->older;
1173		}
1174	    }
1175	    if (xuse->newer != FT_UINT_MAX) {
1176		xtmp = (XftGlyphUsage *) font->glyphs[xuse->newer];
1177		if (xtmp != NULL) {
1178		    /* update link around to newest glyph */
1179		    xtmp->older = xuse->older;
1180		}
1181	    }
1182	    if (font->total_inuse) {
1183		font->total_inuse--;
1184	    } else {
1185		fprintf (stderr, "Xft: glyph count error\n");
1186	    }
1187	    if (XftDebug() & XFT_DBG_USAGE)
1188		_XftValidateGlyphUsage(font);
1189	}
1190
1191	free (xftg);
1192	XftMemFree (XFT_MEM_GLYPH, font->sizeof_glyph);
1193	font->glyphs[glyphindex] = NULL;
1194    }
1195    if (font->glyphset && nused)
1196	XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
1197}
1198
1199_X_EXPORT FcBool
1200XftFontCheckGlyph (Display	*dpy,
1201		   XftFont	*pub,
1202		   FcBool	need_bitmaps,
1203		   FT_UInt	glyph,
1204		   FT_UInt	*missing,
1205		   int		*nmissing)
1206{
1207    XftFontInt	    *font = (XftFontInt *) pub;
1208    XftGlyph	    *xftg;
1209    int		    n;
1210
1211    if (glyph >= font->num_glyphs)
1212	return FcFalse;
1213    xftg = font->glyphs[glyph];
1214    if (!xftg || (need_bitmaps && !xftg->glyph_memory))
1215    {
1216	if (!xftg)
1217	{
1218	    xftg = malloc (font->sizeof_glyph);
1219	    if (!xftg)
1220		return FcFalse;
1221	    XftMemAlloc (XFT_MEM_GLYPH, font->sizeof_glyph);
1222
1223	    xftg->bitmap = NULL;
1224	    xftg->glyph_memory = 0;
1225	    xftg->picture = 0;
1226	    font->glyphs[glyph] = xftg;
1227
1228	    if (font->track_mem_usage) {
1229		XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
1230		xuse->older = FT_UINT_MAX;
1231		xuse->newer = FT_UINT_MAX;
1232	    }
1233	}
1234	n = *nmissing;
1235	missing[n++] = glyph;
1236	if (n == XFT_NMISSING)
1237	{
1238	    XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
1239	    n = 0;
1240	}
1241	*nmissing = n;
1242	return FcTrue;
1243    }
1244
1245    /*
1246     * Make unloading faster by moving newly-referenced glyphs to the front
1247     * of the list, leaving the less-used glyphs on the end.
1248     */
1249    if (font->track_mem_usage
1250     && font->total_inuse > 10
1251     && font->newest != FT_UINT_MAX
1252     && font->newest != glyph)
1253    {
1254	XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
1255	XftGlyphUsage *xtmp = (XftGlyphUsage *) font->glyphs[font->newest];
1256	XftGlyphUsage *xold;
1257	XftGlyphUsage *xnew;
1258
1259	/* delink */
1260	xold = (XftGlyphUsage *) font->glyphs[xuse->older];
1261	xnew = (XftGlyphUsage *) font->glyphs[xuse->newer];
1262	assert(xold != NULL);
1263	assert(xnew != NULL);
1264	xold->newer = xuse->newer;
1265	xnew->older = xuse->older;
1266
1267	/* relink */
1268	xnew = (XftGlyphUsage *) font->glyphs[xtmp->newer];
1269	assert(xnew != NULL);
1270	xnew->older = glyph;
1271	xuse->older = font->newest;
1272	xuse->newer = xtmp->newer;
1273	xtmp->newer = glyph;
1274
1275	font->newest = glyph;
1276    }
1277    return FcFalse;
1278}
1279
1280_X_EXPORT FcBool
1281XftCharExists (Display	    *dpy _X_UNUSED,
1282	       XftFont	    *pub,
1283	       FcChar32	     ucs4)
1284{
1285    if (pub->charset)
1286	return FcCharSetHasChar (pub->charset, ucs4);
1287    return FcFalse;
1288}
1289
1290#define Missing	    ((FT_UInt) ~0)
1291
1292_X_EXPORT FT_UInt
1293XftCharIndex (Display	    *dpy,
1294	      XftFont	    *pub,
1295	      FcChar32	    ucs4)
1296{
1297    XftFontInt	*font = (XftFontInt *) pub;
1298    FcChar32	ent, offset;
1299    FT_Face	face;
1300
1301    if (!font->hash_value)
1302	return 0;
1303
1304    ent = ucs4 % (FcChar32)font->hash_value;
1305    offset = 0;
1306    while (font->hash_table[ent].ucs4 != ucs4)
1307    {
1308	if (font->hash_table[ent].ucs4 == (FcChar32) ~0)
1309	{
1310	    if (!XftCharExists (dpy, pub, ucs4))
1311		return 0;
1312	    face  = XftLockFace (pub);
1313	    if (!face)
1314		return 0;
1315	    font->hash_table[ent].ucs4 = ucs4;
1316	    font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4);
1317	    XftUnlockFace (pub);
1318	    break;
1319	}
1320	if (!offset)
1321	{
1322	    offset = ucs4 % (FcChar32)font->rehash_value;
1323	    if (!offset)
1324		offset = 1;
1325	}
1326	ent = ent + offset;
1327	if (ent >= (FcChar32)font->hash_value)
1328	    ent -= (FcChar32)font->hash_value;
1329    }
1330    return font->hash_table[ent].glyph;
1331}
1332
1333/*
1334 * Remove glyph(s) from the font to reduce memory-usage.
1335 */
1336_X_HIDDEN void
1337_XftFontUncacheGlyph (Display *dpy, XftFont *pub)
1338{
1339    XftFontInt	    *font = (XftFontInt *) pub;
1340    unsigned long   glyph_memory;
1341    FT_UInt	    glyphindex;
1342    XftGlyph	    *xftg;
1343
1344    if (!font->glyph_memory)
1345	return;
1346
1347    if (XftDebug() & XFT_DBG_CACHE)
1348	_XftFontValidateMemory (dpy, pub);
1349
1350    if (font->track_mem_usage)
1351    {
1352	/*
1353	 * Remove the oldest glyph from the font.
1354	 */
1355	if (font->newest != FT_UINT_MAX) {
1356	    XftGlyphUsage *xuse = (XftGlyphUsage *) font->glyphs[font->newest];
1357	    if ((glyphindex = xuse->newer) != FT_UINT_MAX)
1358		XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
1359	}
1360    }
1361    else if (font->use_free_glyphs)
1362    {
1363	/*
1364	 * Pick a random glyph from the font and remove it from the cache
1365	 */
1366	glyph_memory = ((unsigned long)rand() % font->glyph_memory);
1367	for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
1368	{
1369	    xftg = font->glyphs[glyphindex];
1370	    if (xftg)
1371	    {
1372		if (xftg->glyph_memory > glyph_memory)
1373		{
1374		    XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
1375		    break;
1376		}
1377		glyph_memory -= xftg->glyph_memory;
1378	    }
1379	}
1380    }
1381    else
1382    {
1383	/*
1384	 * Free all glyphs, since they are part of a set.
1385	 */
1386	if (font->glyphset)
1387	{
1388	    XRenderFreeGlyphSet (dpy, font->glyphset);
1389	    font->glyphset = 0;
1390	}
1391	for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
1392	{
1393	    xftg = font->glyphs[glyphindex];
1394	    if (xftg)
1395	    {
1396		if (xftg->glyph_memory > 0)
1397		{
1398		    XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
1399		}
1400	    }
1401	}
1402    }
1403
1404    if (XftDebug() & XFT_DBG_CACHE)
1405	_XftFontValidateMemory (dpy, pub);
1406}
1407
1408_X_HIDDEN void
1409_XftFontManageMemory (Display *dpy, XftFont *pub)
1410{
1411    XftFontInt	*font = (XftFontInt *) pub;
1412
1413    if (font->max_glyph_memory)
1414    {
1415	if (XftDebug() & XFT_DBG_CACHE)
1416	{
1417	    if (font->glyph_memory > font->max_glyph_memory)
1418		printf ("Reduce memory for font 0x%lx from %lu to %lu\n",
1419			font->glyphset ? font->glyphset : (unsigned long) font,
1420			font->glyph_memory, font->max_glyph_memory);
1421	}
1422	while (font->glyph_memory > font->max_glyph_memory)
1423	    _XftFontUncacheGlyph (dpy, pub);
1424    }
1425    _XftDisplayManageMemory (dpy);
1426}
1427