1 /*
2  * Copyright © 2000 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Keith Packard not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Keith Packard makes no
11  * representations about the suitability of this software for any purpose.  It
12  * is provided "as is" without express or implied warranty.
13  *
14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #include "xftint.h"
24 #include FT_OUTLINE_H
25 #include FT_LCD_FILTER_H
26 
27 #include FT_SYNTHESIS_H
28 
29 /*
30  * Validate the memory info for a font
31  */
32 
33 static void
_XftFontValidateMemory(Display * dpy,XftFont * public)34 _XftFontValidateMemory (Display *dpy, XftFont *public)
35 {
36     XftFontInt	    *font = (XftFontInt *) public;
37     unsigned long   glyph_memory;
38     FT_UInt	    glyphindex;
39     XftGlyph	    *xftg;
40 
41     glyph_memory = 0;
42     for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
43     {
44 	xftg = font->glyphs[glyphindex];
45 	if (xftg)
46 	{
47 	    glyph_memory += xftg->glyph_memory;
48 	}
49     }
50     if (glyph_memory != font->glyph_memory)
51 	printf ("Font glyph cache incorrect has %ld bytes, should have %ld\n",
52 		font->glyph_memory, glyph_memory);
53 }
54 
55 /* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
56  * into a different format. For example, we want to convert a
57  * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
58  * ARGB or ABGR bitmap.
59  *
60  * this function prepares a target descriptor for this operation.
61  *
62  * input :: target bitmap descriptor. The function will set its
63  *          'width', 'rows' and 'pitch' fields, and only these
64  *
65  * slot  :: the glyph slot containing the source bitmap. this
66  *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
67  *
68  * mode  :: the requested final rendering mode. supported values are
69  *          MONO, NORMAL (i.e. gray), LCD and LCD_V
70  *
71  * the function returns the size in bytes of the corresponding buffer,
72  * it's up to the caller to allocate the corresponding memory block
73  * before calling _fill_xrender_bitmap
74  *
75  * it also returns -1 in case of error (e.g. incompatible arguments,
76  * like trying to convert a gray bitmap into a monochrome one)
77  */
78 static int
_compute_xrender_bitmap_size(FT_Bitmap * target,FT_GlyphSlot slot,FT_Render_Mode mode)79 _compute_xrender_bitmap_size( FT_Bitmap*	target,
80 			      FT_GlyphSlot	slot,
81 			      FT_Render_Mode	mode )
82 {
83     FT_Bitmap*	ftbit;
84     int		width, height, pitch;
85 
86     if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
87 	return -1;
88 
89     /* compute the size of the final bitmap */
90     ftbit = &slot->bitmap;
91 
92     width = (int)ftbit->width;
93     height = (int)ftbit->rows;
94     pitch = (width+3) & ~3;
95 
96     switch ( ftbit->pixel_mode )
97     {
98     case FT_PIXEL_MODE_MONO:
99 	if ( mode == FT_RENDER_MODE_MONO )
100 	{
101 	    pitch = (((width+31) & ~31) >> 3);
102 	    break;
103 	}
104 	/* fall-through */
105 
106     case FT_PIXEL_MODE_GRAY:
107 	if ( mode == FT_RENDER_MODE_LCD ||
108 	     mode == FT_RENDER_MODE_LCD_V )
109 	{
110 	    /* each pixel is replicated into a 32-bit ARGB value */
111 	    pitch = width*4;
112 	}
113 	break;
114 
115     case FT_PIXEL_MODE_LCD:
116 	if ( mode != FT_RENDER_MODE_LCD )
117 	    return -1;
118 
119 	/* horz pixel triplets are packed into 32-bit ARGB values */
120 	width /= 3;
121 	pitch = width*4;
122 	break;
123 
124     case FT_PIXEL_MODE_LCD_V:
125 	if ( mode != FT_RENDER_MODE_LCD_V )
126 	    return -1;
127 
128 	/* vert pixel triplets are packed into 32-bit ARGB values */
129 	height /= 3;
130 	pitch = width*4;
131 	break;
132 
133     default:  /* unsupported source format */
134 	return -1;
135     }
136 
137     target->width = (unsigned)width;
138     target->rows = (unsigned)height;
139     target->pitch = pitch;
140     target->buffer = NULL;
141 
142     return pitch * height;
143 }
144 
145 /* this functions converts the glyph bitmap found in a FT_GlyphSlot
146  * into a different format (see _compute_xrender_bitmap_size)
147  *
148  * you should call this function after _compute_xrender_bitmap_size
149  *
150  * target :: target bitmap descriptor. Note that its 'buffer' pointer
151  *           must point to memory allocated by the caller
152  *
153  * slot   :: the glyph slot containing the source bitmap
154  *
155  * mode   :: the requested final rendering mode
156  *
157  * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
158  */
159 static void
_fill_xrender_bitmap(FT_Bitmap * target,FT_GlyphSlot slot,FT_Render_Mode mode,int bgr)160 _fill_xrender_bitmap( FT_Bitmap*	target,
161 		      FT_GlyphSlot	slot,
162 		      FT_Render_Mode	mode,
163 		      int		bgr )
164 {
165     FT_Bitmap*   ftbit = &slot->bitmap;
166 
167     {
168 	unsigned char*	srcLine	= ftbit->buffer;
169         unsigned char*	dstLine	= target->buffer;
170         int		src_pitch = ftbit->pitch;
171         int		width = (int)target->width;
172         int		height = (int)target->rows;
173         int		pitch = target->pitch;
174         int		subpixel;
175         int		h;
176 
177         subpixel = ( mode == FT_RENDER_MODE_LCD ||
178 		     mode == FT_RENDER_MODE_LCD_V );
179 
180 	if ( src_pitch < 0 )
181 	    srcLine -= ((unsigned)src_pitch * (ftbit->rows-1));
182 
183 	switch ( ftbit->pixel_mode )
184 	{
185 	case FT_PIXEL_MODE_MONO:
186 	    if ( subpixel )  /* convert mono to ARGB32 values */
187 	    {
188 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
189 		{
190 		    int x;
191 
192 		    for ( x = 0; x < width; x++ )
193 		    {
194 			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
195 			    ((unsigned int*)dstLine)[x] = 0xffffffffU;
196 		    }
197 		}
198 	    }
199 	    else if ( mode == FT_RENDER_MODE_NORMAL )  /* convert mono to 8-bit gray */
200 	    {
201 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
202 		{
203 		    int x;
204 
205 		    for ( x = 0; x < width; x++ )
206 		    {
207 			if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
208 			    dstLine[x] = 0xff;
209 		    }
210 		}
211 	    }
212 	    else  /* copy mono to mono */
213 	    {
214 		int bytes = (width+7) >> 3;
215 
216 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
217 		    memcpy( dstLine, srcLine, (size_t)bytes );
218 	    }
219 	    break;
220 
221 	case FT_PIXEL_MODE_GRAY:
222 	    if ( subpixel )  /* convert gray to ARGB32 values */
223 	    {
224 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
225 		{
226 		    int		   x;
227 		    unsigned int*  dst = (unsigned int*)dstLine;
228 
229 		    for ( x = 0; x < width; x++ )
230 		    {
231 			unsigned int pix = srcLine[x];
232 
233 			pix |= (pix << 8);
234 			pix |= (pix << 16);
235 
236 			dst[x] = pix;
237 		    }
238 		}
239 	    }
240 	    else  /* copy gray into gray */
241 	    {
242 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
243 		    memcpy( dstLine, srcLine, (size_t)width );
244 	    }
245 	    break;
246 
247 	case FT_PIXEL_MODE_LCD:
248 	    if ( !bgr )
249 	    {
250 		/* convert horizontal RGB into ARGB32 */
251 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
252 		{
253 		    int		   x;
254 		    unsigned char* src = srcLine;
255 		    unsigned int*  dst = (unsigned int*)dstLine;
256 
257 		    for ( x = 0; x < width; x++, src += 3 )
258 		    {
259 			unsigned int pix;
260 
261 			pix = ((unsigned int)src[0] << 16) |
262 			      ((unsigned int)src[1] <<  8) |
263 			      ((unsigned int)src[2]      ) |
264 			      ((unsigned int)src[1] << 24) ;
265 
266 			dst[x] = pix;
267 		    }
268 		}
269 	    }
270 	    else
271 	    {
272 		/* convert horizontal BGR into ARGB32 */
273 		for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
274 		{
275 		    int		   x;
276 		    unsigned char* src = srcLine;
277 		    unsigned int*  dst = (unsigned int*)dstLine;
278 
279 		    for ( x = 0; x < width; x++, src += 3 )
280 		    {
281 			unsigned int pix;
282 
283 			pix = ((unsigned int)src[2] << 16) |
284 			      ((unsigned int)src[1] <<  8) |
285 			      ((unsigned int)src[0]      ) |
286 			      ((unsigned int)src[1] << 24) ;
287 
288 			dst[x] = pix;
289 		    }
290 		}
291 	    }
292 	    break;
293 
294 	default:  /* FT_PIXEL_MODE_LCD_V */
295 	    /* convert vertical RGB into ARGB32 */
296 	    if ( !bgr )
297 	    {
298 		for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
299 		{
300 		    int		   x;
301 		    unsigned char* src = srcLine;
302 		    unsigned int*  dst = (unsigned int*)dstLine;
303 
304 		    for ( x = 0; x < width; x++, src += 1 )
305 		    {
306 			unsigned int  pix;
307 
308 			pix = ((unsigned int)src[0]           << 16) |
309 			      ((unsigned int)src[src_pitch]   <<  8) |
310 			      ((unsigned int)src[src_pitch*2]      ) |
311 			      ((unsigned int)src[src_pitch]   << 24) ;
312 
313 			dst[x] = pix;
314 		    }
315 		}
316 	    }
317 	    else
318 	    {
319 	    for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
320 		{
321 		    int		   x;
322 		    unsigned char* src = srcLine;
323 		    unsigned int*  dst = (unsigned int*)dstLine;
324 
325 		    for ( x = 0; x < width; x++, src += 1 )
326 		    {
327 			unsigned int  pix;
328 
329 			pix = ((unsigned int)src[src_pitch*2] << 16) |
330 			      ((unsigned int)src[src_pitch]   <<  8) |
331 			      ((unsigned int)src[0]                ) |
332 			      ((unsigned int)src[src_pitch]   << 24) ;
333 
334 			dst[x] = pix;
335 		    }
336 		}
337 	    }
338 	}
339     }
340 }
341 
342 _X_EXPORT void
XftFontLoadGlyphs(Display * dpy,XftFont * pub,FcBool need_bitmaps,_Xconst FT_UInt * glyphs,int nglyph)343 XftFontLoadGlyphs (Display	    *dpy,
344 		   XftFont	    *pub,
345 		   FcBool	    need_bitmaps,
346 		   _Xconst FT_UInt  *glyphs,
347 		   int		    nglyph)
348 {
349     XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
350     XftFontInt	    *font = (XftFontInt *) pub;
351     FT_Error	    error;
352     FT_UInt	    glyphindex;
353     FT_GlyphSlot    glyphslot;
354     XftGlyph	    *xftg;
355     Glyph	    glyph;
356     unsigned char   bufLocal[4096];
357     unsigned char   *bufBitmap = bufLocal;
358     int		    bufSize = sizeof (bufLocal);
359     int		    size;
360     int		    width;
361     int		    height;
362     int		    left, right, top, bottom;
363     FT_Bitmap*	    ftbit;
364     FT_Bitmap	    local;
365     FT_Vector	    vector;
366     FT_Face	    face;
367     FT_Render_Mode  mode = FT_RENDER_MODE_MONO;
368 
369     if (!info)
370 	return;
371 
372     face = XftLockFace (&font->public);
373 
374     if (!face)
375 	return;
376 
377     if (font->info.antialias)
378     {
379 	switch (font->info.rgba) {
380 	case FC_RGBA_RGB:
381 	case FC_RGBA_BGR:
382 	    mode = FT_RENDER_MODE_LCD;
383 	    break;
384 	case FC_RGBA_VRGB:
385 	case FC_RGBA_VBGR:
386 	    mode = FT_RENDER_MODE_LCD_V;
387 	    break;
388 	default:
389 	    mode = FT_RENDER_MODE_NORMAL;
390 	}
391     }
392 
393     while (nglyph--)
394     {
395 	glyphindex = *glyphs++;
396 	xftg = font->glyphs[glyphindex];
397 	if (!xftg)
398 	    continue;
399 
400 	if (XftDebug() & XFT_DBG_CACHE)
401 	    _XftFontValidateMemory (dpy, pub);
402 	/*
403 	 * Check to see if this glyph has just been loaded,
404 	 * this happens when drawing the same glyph twice
405 	 * in a single string
406 	 */
407 	if (xftg->glyph_memory)
408 	    continue;
409 
410 	FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter);
411 
412 	error = FT_Load_Glyph (face, glyphindex, font->info.load_flags);
413 	if (error)
414 	{
415 	    /*
416 	     * If anti-aliasing or transforming glyphs and
417 	     * no outline version exists, fallback to the
418 	     * bitmap and let things look bad instead of
419 	     * missing the glyph
420 	     */
421 	    if (font->info.load_flags & FT_LOAD_NO_BITMAP)
422 		error = FT_Load_Glyph (face, glyphindex,
423 				       font->info.load_flags & ~FT_LOAD_NO_BITMAP);
424 	    if (error)
425 		continue;
426 	}
427 
428 #define FLOOR(x)    ((x) & -64)
429 #define CEIL(x)	    (((x)+63) & -64)
430 #define TRUNC(x)    ((x) >> 6)
431 #define ROUND(x)    (((x)+32) & -64)
432 
433 	glyphslot = face->glyph;
434 
435 	/*
436 	 * Embolden if required
437 	 */
438 	if (font->info.embolden) FT_GlyphSlot_Embolden(glyphslot);
439 
440 	/*
441 	 * Compute glyph metrics from FreeType information
442 	 */
443 	if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
444 	{
445 	    /*
446 	     * calculate the true width by transforming all four corners.
447 	     */
448 	    int xc, yc;
449 	    left = right = top = bottom = 0;
450 	    for(xc = 0; xc <= 1; xc ++) {
451 		for(yc = 0; yc <= 1; yc++) {
452 		    vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width;
453 		    vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height;
454 		    FT_Vector_Transform(&vector, &font->info.matrix);
455 		    if (XftDebug() & XFT_DBG_GLYPH)
456 			printf("Trans %d %d: %d %d\n", (int) xc, (int) yc,
457 			       (int) vector.x, (int) vector.y);
458 		    if(xc == 0 && yc == 0) {
459 			left = right = (int)vector.x;
460 			top = bottom = (int)vector.y;
461 		    } else {
462 			if(left	  > vector.x) left   = (int)vector.x;
463 			if(right  < vector.x) right  = (int)vector.x;
464 			if(bottom > vector.y) bottom = (int)vector.y;
465 			if(top	  < vector.y) top    = (int)vector.y;
466 		    }
467 
468 		}
469 	    }
470 	    left   = (int)FLOOR(left);
471 	    right  = (int)CEIL(right);
472 	    bottom = (int)FLOOR(bottom);
473 	    top	   = CEIL(top);
474 
475 	} else {
476 	    left   = (int)FLOOR( glyphslot->metrics.horiBearingX );
477 	    right  = (int)CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width );
478 
479 	    top    = (int)CEIL( glyphslot->metrics.horiBearingY );
480 	    bottom = (int)FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
481 	}
482 
483 	width = TRUNC(right - left);
484 	height = TRUNC( top - bottom );
485 
486 	/*
487 	 * Clip charcell glyphs to the bounding box
488 	 * XXX transformed?
489 	 */
490 	if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
491 	{
492 	    if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
493 	    {
494 		if (TRUNC(bottom) > font->public.max_advance_width)
495 		{
496 		    int adjust;
497 
498 		    adjust = bottom - (font->public.max_advance_width << 6);
499 		    if (adjust > top)
500 			adjust = top;
501 		    top -= adjust;
502 		    bottom -= adjust;
503 		    height = font->public.max_advance_width;
504 		}
505 	    }
506 	    else
507 	    {
508 		if (TRUNC(right) > font->public.max_advance_width)
509 		{
510 		    int adjust;
511 
512 		    adjust = right - (font->public.max_advance_width << 6);
513 		    if (adjust > left)
514 			adjust = left;
515 		    left -= adjust;
516 		    right -= adjust;
517 		    width = font->public.max_advance_width;
518 		}
519 	    }
520 	}
521 
522 	if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
523 	{
524 	    error = FT_Render_Glyph( face->glyph, mode );
525 	    if (error)
526 		continue;
527 	}
528 
529 	FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
530 
531 	if (font->info.spacing >= FC_MONO)
532 	{
533 	    if (font->info.transform)
534 	    {
535 		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
536 		{
537 		    vector.x = 0;
538 		    vector.y = -face->size->metrics.max_advance;
539 		}
540 		else
541 		{
542 		    vector.x = face->size->metrics.max_advance;
543 		    vector.y = 0;
544 		}
545 		FT_Vector_Transform (&vector, &font->info.matrix);
546 		xftg->metrics.xOff = (short)(vector.x >> 6);
547 		xftg->metrics.yOff = (short)(-(vector.y >> 6));
548 	    }
549 	    else
550 	    {
551 		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
552 		{
553 		    xftg->metrics.xOff = 0;
554 		    xftg->metrics.yOff = (short)(-font->public.max_advance_width);
555 		}
556 		else
557 		{
558 		    xftg->metrics.xOff = (short)(font->public.max_advance_width);
559 		    xftg->metrics.yOff = 0;
560 		}
561 	    }
562 	}
563 	else
564 	{
565 	    xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x)));
566 	    xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y)));
567 	}
568 
569 	/* compute the size of the final bitmap */
570 	ftbit = &glyphslot->bitmap;
571 
572 	width = (int)ftbit->width;
573 	height = (int)ftbit->rows;
574 
575 	if (XftDebug() & XFT_DBG_GLYPH)
576 	{
577 	    printf ("glyph %d:\n", (int) glyphindex);
578 	    printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n",
579 		    (int) glyphslot->metrics.horiBearingX,
580 		    (int) glyphslot->metrics.horiBearingY,
581 		    (int) glyphslot->metrics.width,
582 		    (int) glyphslot->metrics.height,
583 		    left, right, top, bottom,
584 		    width, height);
585 	    if (XftDebug() & XFT_DBG_GLYPHV)
586 	    {
587 		int		x, y;
588 		unsigned char	*line;
589 
590 		line = ftbit->buffer;
591 		if (ftbit->pitch < 0)
592 		    line -= ftbit->pitch*(height-1);
593 
594 		for (y = 0; y < height; y++)
595 		{
596 		    if (font->info.antialias)
597 		    {
598 			static const char    den[] = { " .:;=+*#" };
599 			for (x = 0; x < width; x++)
600 			    printf ("%c", den[line[x] >> 5]);
601 		    }
602 		    else
603 		    {
604 			for (x = 0; x < width * 8; x++)
605 			{
606 			    printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
607 			}
608 		    }
609 		    printf ("|\n");
610 		    line += ftbit->pitch;
611 		}
612 		printf ("\n");
613 	    }
614 	}
615 
616 	size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
617 	if ( size < 0 )
618 	    continue;
619 
620 	xftg->metrics.width  = (unsigned short)local.width;
621 	xftg->metrics.height = (unsigned short)local.rows;
622 	xftg->metrics.x      = (short)(- glyphslot->bitmap_left);
623 	xftg->metrics.y      = (short)(  glyphslot->bitmap_top);
624 
625 	/*
626 	 * If the glyph is relatively large (> 1% of server memory),
627 	 * don't send it until necessary.
628 	 */
629 	if (!need_bitmaps && size > info->max_glyph_memory / 100)
630 	    continue;
631 
632 	/*
633 	 * Make sure there is enough buffer space for the glyph.
634 	 */
635 	if (size > bufSize)
636 	{
637 	    if (bufBitmap != bufLocal)
638 		free (bufBitmap);
639 	    bufBitmap = (unsigned char *) malloc ((size_t)size);
640 	    if (!bufBitmap)
641 		continue;
642 	    bufSize = size;
643 	}
644 	memset (bufBitmap, 0, (size_t)size);
645 
646 	local.buffer = bufBitmap;
647 
648 	_fill_xrender_bitmap( &local, glyphslot, mode,
649 			      (font->info.rgba == FC_RGBA_BGR ||
650 			       font->info.rgba == FC_RGBA_VBGR ) );
651 
652 	/*
653 	 * Copy or convert into local buffer.
654 	 */
655 
656 	/*
657 	 * Use the glyph index as the wire encoding; it
658 	 * might be more efficient for some locales to map
659 	 * these by first usage to smaller values, but that
660 	 * would require persistently storing the map when
661 	 * glyphs were freed.
662 	 */
663 	glyph = (Glyph) glyphindex;
664 
665 	xftg->glyph_memory = (size_t)size + sizeof (XftGlyph);
666 	if (font->format)
667 	{
668 	    if (!font->glyphset)
669 		font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
670 	    if ( mode == FT_RENDER_MODE_MONO )
671 	    {
672 		/* swap bits in each byte */
673 		if (BitmapBitOrder (dpy) != MSBFirst)
674 		{
675 		    unsigned char   *line = (unsigned char*)bufBitmap;
676 		    int		    i = size;
677 
678 		    while (i--)
679 		    {
680 			int c = *line;
681 			c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
682 			c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
683 			c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
684 			*line++ = (unsigned char)c;
685 		    }
686 		}
687 	    }
688 	    else if ( mode != FT_RENDER_MODE_NORMAL )
689 	    {
690 		/* invert ARGB <=> BGRA */
691 		if (ImageByteOrder (dpy) != XftNativeByteOrder ())
692 		    XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
693 	    }
694 	    XRenderAddGlyphs (dpy, font->glyphset, &glyph,
695 			      &xftg->metrics, 1,
696 			      (char *) bufBitmap, size);
697 	}
698 	else
699 	{
700 	    if (size)
701 	    {
702 		xftg->bitmap = malloc ((size_t)size);
703 		if (xftg->bitmap)
704 		    memcpy (xftg->bitmap, bufBitmap, (size_t)size);
705 	    }
706 	    else
707 		xftg->bitmap = NULL;
708 	}
709 
710 	font->glyph_memory += xftg->glyph_memory;
711 	info->glyph_memory += xftg->glyph_memory;
712 	if (XftDebug() & XFT_DBG_CACHE)
713 	    _XftFontValidateMemory (dpy, pub);
714 	if (XftDebug() & XFT_DBG_CACHEV)
715 	    printf ("Caching glyph 0x%x size %ld\n", glyphindex,
716 		    xftg->glyph_memory);
717     }
718     if (bufBitmap != bufLocal)
719 	free (bufBitmap);
720     XftUnlockFace (&font->public);
721 }
722 
723 _X_EXPORT void
XftFontUnloadGlyphs(Display * dpy,XftFont * pub,_Xconst FT_UInt * glyphs,int nglyph)724 XftFontUnloadGlyphs (Display		*dpy,
725 		     XftFont		*pub,
726 		     _Xconst FT_UInt	*glyphs,
727 		     int		nglyph)
728 {
729     XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
730     XftFontInt	    *font = (XftFontInt *) pub;
731     XftGlyph	    *xftg;
732     FT_UInt	    glyphindex;
733     Glyph	    glyphBuf[1024];
734     int		    nused;
735 
736     nused = 0;
737     while (nglyph--)
738     {
739 	glyphindex = *glyphs++;
740 	xftg = font->glyphs[glyphindex];
741 	if (!xftg)
742 	    continue;
743 	if (xftg->glyph_memory)
744 	{
745 	    if (font->format)
746 	    {
747 		if (font->glyphset)
748 		{
749 		    glyphBuf[nused++] = (Glyph) glyphindex;
750 		    if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
751 		    {
752 			XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
753 			nused = 0;
754 		    }
755 		}
756 	    }
757 	    else
758 	    {
759 		if (xftg->bitmap)
760 		    free (xftg->bitmap);
761 	    }
762 	    font->glyph_memory -= xftg->glyph_memory;
763 	    if (info)
764 		info->glyph_memory -= xftg->glyph_memory;
765 	}
766 	free (xftg);
767 	XftMemFree (XFT_MEM_GLYPH, sizeof (XftGlyph));
768 	font->glyphs[glyphindex] = NULL;
769     }
770     if (font->glyphset && nused)
771 	XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
772 }
773 
774 _X_EXPORT FcBool
XftFontCheckGlyph(Display * dpy,XftFont * pub,FcBool need_bitmaps,FT_UInt glyph,FT_UInt * missing,int * nmissing)775 XftFontCheckGlyph (Display	*dpy,
776 		   XftFont	*pub,
777 		   FcBool	need_bitmaps,
778 		   FT_UInt	glyph,
779 		   FT_UInt	*missing,
780 		   int		*nmissing)
781 {
782     XftFontInt	    *font = (XftFontInt *) pub;
783     XftGlyph	    *xftg;
784     int		    n;
785 
786     if (glyph >= font->num_glyphs)
787 	return FcFalse;
788     xftg = font->glyphs[glyph];
789     if (!xftg || (need_bitmaps && !xftg->glyph_memory))
790     {
791 	if (!xftg)
792 	{
793 	    xftg = (XftGlyph *) malloc (sizeof (XftGlyph));
794 	    if (!xftg)
795 		return FcFalse;
796 	    XftMemAlloc (XFT_MEM_GLYPH, sizeof (XftGlyph));
797 	    xftg->bitmap = NULL;
798 	    xftg->glyph_memory = 0;
799 	    font->glyphs[glyph] = xftg;
800 	}
801 	n = *nmissing;
802 	missing[n++] = glyph;
803 	if (n == XFT_NMISSING)
804 	{
805 	    XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
806 	    n = 0;
807 	}
808 	*nmissing = n;
809 	return FcTrue;
810     }
811     else
812 	return FcFalse;
813 }
814 
815 _X_EXPORT FcBool
XftCharExists(Display * dpy,XftFont * pub,FcChar32 ucs4)816 XftCharExists (Display	    *dpy,
817 	       XftFont	    *pub,
818 	       FcChar32    ucs4)
819 {
820     if (pub->charset)
821 	return FcCharSetHasChar (pub->charset, ucs4);
822     return FcFalse;
823 }
824 
825 #define Missing	    ((FT_UInt) ~0)
826 
827 _X_EXPORT FT_UInt
XftCharIndex(Display * dpy,XftFont * pub,FcChar32 ucs4)828 XftCharIndex (Display	    *dpy,
829 	      XftFont	    *pub,
830 	      FcChar32	    ucs4)
831 {
832     XftFontInt	*font = (XftFontInt *) pub;
833     FcChar32	ent, offset;
834     FT_Face	face;
835 
836     if (!font->hash_value)
837 	return 0;
838 
839     ent = ucs4 % (FcChar32)font->hash_value;
840     offset = 0;
841     while (font->hash_table[ent].ucs4 != ucs4)
842     {
843 	if (font->hash_table[ent].ucs4 == (FcChar32) ~0)
844 	{
845 	    if (!XftCharExists (dpy, pub, ucs4))
846 		return 0;
847 	    face  = XftLockFace (pub);
848 	    if (!face)
849 		return 0;
850 	    font->hash_table[ent].ucs4 = ucs4;
851 	    font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4);
852 	    XftUnlockFace (pub);
853 	    break;
854 	}
855 	if (!offset)
856 	{
857 	    offset = ucs4 % (FcChar32)font->rehash_value;
858 	    if (!offset)
859 		offset = 1;
860 	}
861 	ent = ent + offset;
862 	if (ent >= font->hash_value)
863 	    ent -= (FcChar32)font->hash_value;
864     }
865     return font->hash_table[ent].glyph;
866 }
867 
868 /*
869  * Pick a random glyph from the font and remove it from the cache
870  */
871 _X_HIDDEN void
_XftFontUncacheGlyph(Display * dpy,XftFont * pub)872 _XftFontUncacheGlyph (Display *dpy, XftFont *pub)
873 {
874     XftFontInt	    *font = (XftFontInt *) pub;
875     unsigned long   glyph_memory;
876     FT_UInt	    glyphindex;
877     XftGlyph	    *xftg;
878 
879     if (!font->glyph_memory)
880 	return;
881     if (font->use_free_glyphs)
882     {
883 	glyph_memory = ((unsigned long)rand() % font->glyph_memory);
884     }
885     else
886     {
887 	if (font->glyphset)
888 	{
889 	    XRenderFreeGlyphSet (dpy, font->glyphset);
890 	    font->glyphset = 0;
891 	}
892 	glyph_memory = 0;
893     }
894 
895     if (XftDebug() & XFT_DBG_CACHE)
896 	_XftFontValidateMemory (dpy, pub);
897     for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
898     {
899 	xftg = font->glyphs[glyphindex];
900 	if (xftg)
901 	{
902 	    if (xftg->glyph_memory > glyph_memory)
903 	    {
904 		if (XftDebug() & XFT_DBG_CACHEV)
905 		    printf ("Uncaching glyph 0x%x size %ld\n",
906 			    glyphindex, xftg->glyph_memory);
907 		XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
908 		if (!font->use_free_glyphs)
909 		    continue;
910 		break;
911 	    }
912 	    glyph_memory -= xftg->glyph_memory;
913 	}
914     }
915     if (XftDebug() & XFT_DBG_CACHE)
916 	_XftFontValidateMemory (dpy, pub);
917 }
918 
919 _X_HIDDEN void
_XftFontManageMemory(Display * dpy,XftFont * pub)920 _XftFontManageMemory (Display *dpy, XftFont *pub)
921 {
922     XftFontInt	*font = (XftFontInt *) pub;
923 
924     if (font->max_glyph_memory)
925     {
926 	if (XftDebug() & XFT_DBG_CACHE)
927 	{
928 	    if (font->glyph_memory > font->max_glyph_memory)
929 		printf ("Reduce memory for font 0x%lx from %ld to %ld\n",
930 			font->glyphset ? font->glyphset : (unsigned long) font,
931 			font->glyph_memory, font->max_glyph_memory);
932 	}
933 	while (font->glyph_memory > font->max_glyph_memory)
934 	    _XftFontUncacheGlyph (dpy, pub);
935     }
936     _XftDisplayManageMemory (dpy);
937 }
938