Home | History | Annotate | Line # | Download | only in src
      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 
     32 typedef double m3x3[3][3];
     33 
     34 static void
     35 m3x3_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 
     41 static void
     42 m3x3_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 
     52 static void
     53 m3x3_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 
     76 static 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  */
    101 static 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  */
    183 static 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  */
    326 static 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  */
    446 static 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
    635 XftFontLoadGlyphs (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 		short maximum_x = (short)(font->public.max_advance_width);
    848 		short maximum_y = (short)(-font->public.max_advance_width);
    849 		short trimmed_x = (short)(TRUNC(ROUND(glyphslot->advance.x)));
    850 		short trimmed_y = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
    851 		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
    852 		{
    853 		    xftg->metrics.xOff = 0;
    854 		    xftg->metrics.yOff = min(maximum_y,trimmed_y);
    855 		}
    856 		else
    857 		{
    858 		    xftg->metrics.xOff = min(maximum_x,trimmed_x);
    859 		    xftg->metrics.yOff = 0;
    860 		}
    861 	    }
    862 	}
    863 	else
    864 	{
    865 	    xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x)));
    866 	    xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
    867 	}
    868 
    869 	/* compute the size of the final bitmap */
    870 	ftbit = &glyphslot->bitmap;
    871 
    872 	width = (int)ftbit->width;
    873 	height = (int)ftbit->rows;
    874 
    875 	if (XftDebug() & XFT_DBG_GLYPH)
    876 	{
    877 	    printf ("glyph %d:\n", (int) glyphindex);
    878 	    printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n",
    879 		    (int) glyphslot->metrics.horiBearingX,
    880 		    (int) glyphslot->metrics.horiBearingY,
    881 		    (int) glyphslot->metrics.width,
    882 		    (int) glyphslot->metrics.height,
    883 		    left, right, top, bottom,
    884 		    width, height);
    885 	    if (XftDebug() & XFT_DBG_GLYPHV)
    886 	    {
    887 		int		x, y;
    888 		unsigned char	*line;
    889 
    890 		line = ftbit->buffer;
    891 		if (ftbit->pitch < 0)
    892 		    line -= ftbit->pitch*(height-1);
    893 
    894 		for (y = 0; y < height; y++)
    895 		{
    896 		    if (font->info.antialias)
    897 		    {
    898 			static const char    den[] = { " .:;=+*#" };
    899 			for (x = 0; x < width; x++)
    900 			    printf ("%c", den[line[x] >> 5]);
    901 		    }
    902 		    else
    903 		    {
    904 			for (x = 0; x < width * 8; x++)
    905 			{
    906 			    printf ("%c", (line[x>>3] & (1 << (x & 7))) ? '#' : ' ');
    907 			}
    908 		    }
    909 		    printf ("|\n");
    910 		    line += ftbit->pitch;
    911 		}
    912 		printf ("\n");
    913 	    }
    914 	}
    915 
    916 	m3x3_uniform(m);
    917 	size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL, m );
    918 	if ( size < 0 )
    919 	    continue;
    920 
    921 	xftg->metrics.width  = (unsigned short)local.width;
    922 	xftg->metrics.height = (unsigned short)local.rows;
    923 	if (glyph_transform)
    924 	{
    925 	    m3x3 mi;
    926 
    927 	    m3x3_invert(m, mi);
    928 	    vector.x = - glyphslot->bitmap_left;
    929 	    vector.y =   glyphslot->bitmap_top;
    930 	    m3x3_transform(&vector, mi);
    931 	    xftg->metrics.x = (short)vector.x;
    932 	    xftg->metrics.y = (short)vector.y;
    933 	}
    934 	else
    935 	{
    936 	    xftg->metrics.x = (short)(- glyphslot->bitmap_left);
    937 	    xftg->metrics.y = (short)(  glyphslot->bitmap_top);
    938 	}
    939 
    940 	/*
    941 	 * If the glyph is relatively large (> 1% of server memory),
    942 	 * don't send it until necessary.
    943 	 */
    944 	if (!need_bitmaps && ((unsigned long) size > (info->max_glyph_memory / 100)))
    945 	    continue;
    946 
    947 	/*
    948 	 * Make sure there is enough buffer space for the glyph.
    949 	 */
    950 	if (size > bufSize)
    951 	{
    952 	    if (bufBitmap != bufLocal)
    953 		free (bufBitmap);
    954 	    bufBitmap = (unsigned char *) malloc ((size_t)size);
    955 	    if (!bufBitmap)
    956 		continue;
    957 	    bufSize = size;
    958 	}
    959 	memset (bufBitmap, 0, (size_t)size);
    960 
    961 	local.buffer = bufBitmap;
    962 
    963 	if (mode == FT_RENDER_MODE_NORMAL && glyph_transform)
    964 	    _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, m);
    965 	else
    966 	    _fill_xrender_bitmap( &local, glyphslot, mode,
    967 				 (font->info.rgba == FC_RGBA_BGR ||
    968 				  font->info.rgba == FC_RGBA_VBGR) );
    969 
    970 	/*
    971 	 * Copy or convert into local buffer.
    972 	 */
    973 
    974 	/*
    975 	 * Use the glyph index as the wire encoding; it
    976 	 * might be more efficient for some locales to map
    977 	 * these by first usage to smaller values, but that
    978 	 * would require persistently storing the map when
    979 	 * glyphs were freed.
    980 	 */
    981 	glyph = (Glyph) glyphindex;
    982 
    983 	if (xftg->picture)
    984 	{
    985 	    XRenderFreePicture(dpy, xftg->picture);
    986 	    xftg->picture = 0;
    987 	}
    988 	xftg->glyph_memory = (size_t)size + font->sizeof_glyph;
    989 	if (font->format)
    990 	{
    991 	    if (!font->glyphset)
    992 		font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
    993 	    if ( mode == FT_RENDER_MODE_MONO )
    994 	    {
    995 		/* swap bits in each byte */
    996 		if (BitmapBitOrder (dpy) != MSBFirst)
    997 		{
    998 		    unsigned char   *line = (unsigned char*)bufBitmap;
    999 		    int		    i = size;
   1000 
   1001 		    while (i--)
   1002 		    {
   1003 			int c = *line;
   1004 			c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
   1005 			c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
   1006 			c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
   1007 			*line++ = (unsigned char)c;
   1008 		    }
   1009 		}
   1010 	    }
   1011 	    else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL)
   1012 	    {
   1013 		/* invert ARGB <=> BGRA */
   1014 		if (ImageByteOrder (dpy) != XftNativeByteOrder ())
   1015 		    XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
   1016 	    }
   1017 
   1018 	    if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
   1019 	    {
   1020 		Pixmap pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), local.width, local.rows, 32);
   1021 		GC gc = XCreateGC(dpy, pixmap, 0, NULL);
   1022 		XImage image = {
   1023 		    (int) local.width, (int) local.rows, 0, ZPixmap, (char *)bufBitmap,
   1024 		    dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32,
   1025 		    32, (int) (local.width * 4 - (unsigned) local.pitch), 32,
   1026 		    0, 0, 0, NULL, { NULL }
   1027 		};
   1028 
   1029 		XInitImage(&image);
   1030 		XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, local.width, local.rows);
   1031 		xftg->picture = XRenderCreatePicture(dpy, pixmap, font->format, 0, NULL);
   1032 
   1033 		XFreeGC(dpy, gc);
   1034 		XFreePixmap(dpy, pixmap);
   1035 		/*
   1036 		 * Record 256 times higher memory pressure for unrotated
   1037 		 * pictures, and maximum for rotated pictures.
   1038 		 */
   1039 		if (font->info.matrix.xy || font->info.matrix.yx)
   1040 		    xftg->glyph_memory += font->max_glyph_memory - (unsigned long) size;
   1041 		else
   1042 		    xftg->glyph_memory += (size_t)size * 255;
   1043 	    }
   1044 	    else
   1045 		XRenderAddGlyphs (dpy, font->glyphset, &glyph,
   1046 				  &xftg->metrics, 1,
   1047 				  (char *) bufBitmap, size);
   1048 	}
   1049 	else
   1050 	{
   1051 	    if (size)
   1052 	    {
   1053 		xftg->bitmap = malloc ((size_t)size);
   1054 		if (xftg->bitmap)
   1055 		    memcpy (xftg->bitmap, bufBitmap, (size_t)size);
   1056 	    }
   1057 	    else
   1058 		xftg->bitmap = NULL;
   1059 	}
   1060 
   1061 	font->glyph_memory += xftg->glyph_memory;
   1062 	info->glyph_memory += xftg->glyph_memory;
   1063 	if (XftDebug() & XFT_DBG_CACHE)
   1064 	    _XftFontValidateMemory (dpy, pub);
   1065 	if (XftDebug() & XFT_DBG_CACHEV)
   1066 	    printf ("Caching glyph 0x%x size %lu\n", glyphindex,
   1067 		    xftg->glyph_memory);
   1068 
   1069 	if (font->track_mem_usage) {
   1070 	    XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
   1071 
   1072 	    if (font->newest == FT_UINT_MAX) {
   1073 		xuse->older = glyphindex;
   1074 	        xuse->newer = glyphindex;
   1075 		if (XftDebug() & XFT_DBG_USAGE)
   1076 		    printf("alloc %p -> %d: %p USE %d.%d\n",
   1077 			    (void *) font, glyphindex,
   1078 			    (void *) xuse, xuse->older, xuse->newer);
   1079 	    } else {
   1080 		XftGlyphUsage *xnew;
   1081 		XftGlyphUsage *xold;
   1082 
   1083 		assert(font->glyphs[font->newest] != NULL);
   1084 		xnew = (XftGlyphUsage *) font->glyphs[font->newest];
   1085 
   1086 		assert(font->glyphs[xnew->newer] != NULL);
   1087 		xold = (XftGlyphUsage *) font->glyphs[xnew->newer];
   1088 
   1089 		xuse->older = font->newest;
   1090 		xuse->newer = xnew->newer;
   1091 		xnew->newer = glyphindex;
   1092 		xold->older = glyphindex;
   1093 		if (XftDebug() & XFT_DBG_USAGE)
   1094 		    printf("alloc %p -> %d: %p USE %d.%d, %p NEW %d.%d %p OLD %d.%d\n",
   1095 			    (void *) font, glyphindex,
   1096 			    (void *) xuse, xuse->older, xuse->newer,
   1097 			    (void *) xnew, xnew->older, xnew->newer,
   1098 			    (void *) xold, xold->older, xold->newer);
   1099 	    }
   1100 
   1101 	    font->newest = glyphindex;
   1102 	    font->total_inuse++;
   1103 	    if (XftDebug() & XFT_DBG_USAGE)
   1104 		_XftValidateGlyphUsage(font);
   1105 	}
   1106     }
   1107     if (bufBitmap != bufLocal)
   1108 	free (bufBitmap);
   1109     XftUnlockFace (&font->public);
   1110 }
   1111 
   1112 _X_EXPORT void
   1113 XftFontUnloadGlyphs (Display		*dpy,
   1114 		     XftFont		*pub,
   1115 		     _Xconst FT_UInt	*glyphs,
   1116 		     int		nglyph)
   1117 {
   1118     XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
   1119     XftFontInt	    *font = (XftFontInt *) pub;
   1120     XftGlyph	    *xftg;
   1121     FT_UInt	    glyphindex;
   1122     Glyph	    glyphBuf[1024];
   1123     int		    nused;
   1124 
   1125     nused = 0;
   1126     while (nglyph--)
   1127     {
   1128 	glyphindex = *glyphs++;
   1129 	xftg = font->glyphs[glyphindex];
   1130 	if (!xftg)
   1131 	    continue;
   1132 	if (xftg->glyph_memory)
   1133 	{
   1134 	    if (XftDebug() & XFT_DBG_CACHEV)
   1135 		printf ("Uncaching glyph 0x%x size %lu\n",
   1136 			glyphindex, xftg->glyph_memory);
   1137 	    if (font->format)
   1138 	    {
   1139 		if (xftg->picture)
   1140 		    XRenderFreePicture(dpy, xftg->picture);
   1141 		else if (font->glyphset)
   1142 		{
   1143 		    glyphBuf[nused++] = (Glyph) glyphindex;
   1144 		    if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
   1145 		    {
   1146 			XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
   1147 			nused = 0;
   1148 		    }
   1149 		}
   1150 	    }
   1151 	    else if (xftg->bitmap)
   1152 		free (xftg->bitmap);
   1153 	    font->glyph_memory -= xftg->glyph_memory;
   1154 	    if (info)
   1155 		info->glyph_memory -= xftg->glyph_memory;
   1156 	}
   1157 
   1158 	if (font->track_mem_usage) {
   1159 	    XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
   1160 	    XftGlyphUsage *xtmp;
   1161 
   1162 	    if (XftDebug() & XFT_DBG_USAGE)
   1163 		printf("free %p -> %p USE %d.%d\n",
   1164 		       (void *) font, (void *) xuse, xuse->older, xuse->newer);
   1165 
   1166 	    if (xuse->older != FT_UINT_MAX) {
   1167 		xtmp = (XftGlyphUsage *) font->glyphs[xuse->older];
   1168 		if (xtmp != NULL) {
   1169 		    /* update link around to oldest glyph */
   1170 		    xtmp->newer = xuse->newer;
   1171 		}
   1172 		if (font->newest == glyphindex) {
   1173 		    if (font->newest == xuse->older)
   1174 			font->newest = FT_UINT_MAX;
   1175 		    else
   1176 			font->newest = xuse->older;
   1177 		}
   1178 	    }
   1179 	    if (xuse->newer != FT_UINT_MAX) {
   1180 		xtmp = (XftGlyphUsage *) font->glyphs[xuse->newer];
   1181 		if (xtmp != NULL) {
   1182 		    /* update link around to newest glyph */
   1183 		    xtmp->older = xuse->older;
   1184 		}
   1185 	    }
   1186 	    if (font->total_inuse) {
   1187 		font->total_inuse--;
   1188 	    } else {
   1189 		fprintf (stderr, "Xft: glyph count error\n");
   1190 	    }
   1191 	    if (XftDebug() & XFT_DBG_USAGE)
   1192 		_XftValidateGlyphUsage(font);
   1193 	}
   1194 
   1195 	free (xftg);
   1196 	XftMemFree (XFT_MEM_GLYPH, font->sizeof_glyph);
   1197 	font->glyphs[glyphindex] = NULL;
   1198     }
   1199     if (font->glyphset && nused)
   1200 	XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
   1201 }
   1202 
   1203 _X_EXPORT FcBool
   1204 XftFontCheckGlyph (Display	*dpy,
   1205 		   XftFont	*pub,
   1206 		   FcBool	need_bitmaps,
   1207 		   FT_UInt	glyph,
   1208 		   FT_UInt	*missing,
   1209 		   int		*nmissing)
   1210 {
   1211     XftFontInt	    *font = (XftFontInt *) pub;
   1212     XftGlyph	    *xftg;
   1213     int		    n;
   1214 
   1215     if (glyph >= font->num_glyphs)
   1216 	return FcFalse;
   1217     xftg = font->glyphs[glyph];
   1218     if (!xftg || (need_bitmaps && !xftg->glyph_memory))
   1219     {
   1220 	if (!xftg)
   1221 	{
   1222 	    xftg = malloc (font->sizeof_glyph);
   1223 	    if (!xftg)
   1224 		return FcFalse;
   1225 	    XftMemAlloc (XFT_MEM_GLYPH, font->sizeof_glyph);
   1226 
   1227 	    xftg->bitmap = NULL;
   1228 	    xftg->glyph_memory = 0;
   1229 	    xftg->picture = 0;
   1230 	    font->glyphs[glyph] = xftg;
   1231 
   1232 	    if (font->track_mem_usage) {
   1233 		XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
   1234 		xuse->older = FT_UINT_MAX;
   1235 		xuse->newer = FT_UINT_MAX;
   1236 	    }
   1237 	}
   1238 	n = *nmissing;
   1239 	missing[n++] = glyph;
   1240 	if (n == XFT_NMISSING)
   1241 	{
   1242 	    XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
   1243 	    n = 0;
   1244 	}
   1245 	*nmissing = n;
   1246 	return FcTrue;
   1247     }
   1248 
   1249     /*
   1250      * Make unloading faster by moving newly-referenced glyphs to the front
   1251      * of the list, leaving the less-used glyphs on the end.
   1252      *
   1253      * If the glyph is zero, the older/newer data may not have been set.
   1254      */
   1255     if (glyph != 0
   1256      && font->track_mem_usage
   1257      && font->total_inuse > 10
   1258      && font->newest != FT_UINT_MAX
   1259      && font->newest != glyph)
   1260     {
   1261 	XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
   1262 	XftGlyphUsage *xtmp = (XftGlyphUsage *) font->glyphs[font->newest];
   1263 	XftGlyphUsage *xold;
   1264 	XftGlyphUsage *xnew;
   1265 
   1266 	/* delink */
   1267 	xold = (XftGlyphUsage *) font->glyphs[xuse->older];
   1268 	xnew = (XftGlyphUsage *) font->glyphs[xuse->newer];
   1269 	assert(xold != NULL);
   1270 	assert(xnew != NULL);
   1271 	xold->newer = xuse->newer;
   1272 	xnew->older = xuse->older;
   1273 
   1274 	/* relink */
   1275 	xnew = (XftGlyphUsage *) font->glyphs[xtmp->newer];
   1276 	assert(xnew != NULL);
   1277 	xnew->older = glyph;
   1278 	xuse->older = font->newest;
   1279 	xuse->newer = xtmp->newer;
   1280 	xtmp->newer = glyph;
   1281 
   1282 	font->newest = glyph;
   1283     }
   1284     return FcFalse;
   1285 }
   1286 
   1287 _X_EXPORT FcBool
   1288 XftCharExists (Display	    *dpy _X_UNUSED,
   1289 	       XftFont	    *pub,
   1290 	       FcChar32	     ucs4)
   1291 {
   1292     if (pub->charset)
   1293 	return FcCharSetHasChar (pub->charset, ucs4);
   1294     return FcFalse;
   1295 }
   1296 
   1297 #define Missing	    ((FT_UInt) ~0)
   1298 
   1299 _X_EXPORT FT_UInt
   1300 XftCharIndex (Display	    *dpy,
   1301 	      XftFont	    *pub,
   1302 	      FcChar32	    ucs4)
   1303 {
   1304     XftFontInt	*font = (XftFontInt *) pub;
   1305     FcChar32	ent, offset;
   1306     FT_Face	face;
   1307 
   1308     if (!font->hash_value)
   1309 	return 0;
   1310 
   1311     ent = ucs4 % (FcChar32)font->hash_value;
   1312     offset = 0;
   1313     while (font->hash_table[ent].ucs4 != ucs4)
   1314     {
   1315 	if (font->hash_table[ent].ucs4 == (FcChar32) ~0)
   1316 	{
   1317 	    if (!XftCharExists (dpy, pub, ucs4))
   1318 		return 0;
   1319 	    face  = XftLockFace (pub);
   1320 	    if (!face)
   1321 		return 0;
   1322 	    font->hash_table[ent].ucs4 = ucs4;
   1323 	    font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4);
   1324 	    XftUnlockFace (pub);
   1325 	    break;
   1326 	}
   1327 	if (!offset)
   1328 	{
   1329 	    offset = ucs4 % (FcChar32)font->rehash_value;
   1330 	    if (!offset)
   1331 		offset = 1;
   1332 	}
   1333 	ent = ent + offset;
   1334 	if (ent >= (FcChar32)font->hash_value)
   1335 	    ent -= (FcChar32)font->hash_value;
   1336     }
   1337     return font->hash_table[ent].glyph;
   1338 }
   1339 
   1340 /*
   1341  * Remove glyph(s) from the font to reduce memory-usage.
   1342  */
   1343 _X_HIDDEN void
   1344 _XftFontUncacheGlyph (Display *dpy, XftFont *pub)
   1345 {
   1346     XftFontInt	    *font = (XftFontInt *) pub;
   1347     unsigned long   glyph_memory;
   1348     FT_UInt	    glyphindex;
   1349     XftGlyph	    *xftg;
   1350 
   1351     if (!font->glyph_memory)
   1352 	return;
   1353 
   1354     if (XftDebug() & XFT_DBG_CACHE)
   1355 	_XftFontValidateMemory (dpy, pub);
   1356 
   1357     if (font->track_mem_usage)
   1358     {
   1359 	/*
   1360 	 * Remove the oldest glyph from the font.
   1361 	 */
   1362 	if (font->newest != FT_UINT_MAX) {
   1363 	    XftGlyphUsage *xuse = (XftGlyphUsage *) font->glyphs[font->newest];
   1364 	    if ((glyphindex = xuse->newer) != FT_UINT_MAX)
   1365 		XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
   1366 	}
   1367     }
   1368     else if (font->use_free_glyphs)
   1369     {
   1370 	/*
   1371 	 * Pick a random glyph from the font and remove it from the cache
   1372 	 */
   1373 	glyph_memory = ((unsigned long)rand() % font->glyph_memory);
   1374 	for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
   1375 	{
   1376 	    xftg = font->glyphs[glyphindex];
   1377 	    if (xftg)
   1378 	    {
   1379 		if (xftg->glyph_memory > glyph_memory)
   1380 		{
   1381 		    XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
   1382 		    break;
   1383 		}
   1384 		glyph_memory -= xftg->glyph_memory;
   1385 	    }
   1386 	}
   1387     }
   1388     else
   1389     {
   1390 	/*
   1391 	 * Free all glyphs, since they are part of a set.
   1392 	 */
   1393 	if (font->glyphset)
   1394 	{
   1395 	    XRenderFreeGlyphSet (dpy, font->glyphset);
   1396 	    font->glyphset = 0;
   1397 	}
   1398 	for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
   1399 	{
   1400 	    xftg = font->glyphs[glyphindex];
   1401 	    if (xftg)
   1402 	    {
   1403 		if (xftg->glyph_memory > 0)
   1404 		{
   1405 		    XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
   1406 		}
   1407 	    }
   1408 	}
   1409     }
   1410 
   1411     if (XftDebug() & XFT_DBG_CACHE)
   1412 	_XftFontValidateMemory (dpy, pub);
   1413 }
   1414 
   1415 _X_HIDDEN void
   1416 _XftFontManageMemory (Display *dpy, XftFont *pub)
   1417 {
   1418     XftFontInt	*font = (XftFontInt *) pub;
   1419 
   1420     if (font->max_glyph_memory)
   1421     {
   1422 	if (XftDebug() & XFT_DBG_CACHE)
   1423 	{
   1424 	    if (font->glyph_memory > font->max_glyph_memory)
   1425 		printf ("Reduce memory for font 0x%lx from %lu to %lu\n",
   1426 			font->glyphset ? font->glyphset : (unsigned long) font,
   1427 			font->glyph_memory, font->max_glyph_memory);
   1428 	}
   1429 	while (font->glyph_memory > font->max_glyph_memory)
   1430 	    _XftFontUncacheGlyph (dpy, pub);
   1431     }
   1432     _XftDisplayManageMemory (dpy);
   1433 }
   1434