Bug Summary

File:xftglyphs.c
Location:line 503, column 7
Description:Value stored to 'height' is never read

Annotated Source Code

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 <freetype/ftoutln.h>
25#include <freetype/ftlcdfil.h>
26
27#include <freetype/ftsynth.h>
28
29/*
30 * Validate the memory info for a font
31 */
32
33static void
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 */
78static int
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 = ftbit->width;
93 height = 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 = width;
138 target->rows = height;
139 target->pitch = pitch;
140 target->buffer = NULL((void*)0);
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 */
159static void
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 = target->width;
172 int height = 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 -= 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, 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, 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__attribute__((visibility("default"))) void
343XftFontLoadGlyphs (Display *dpy,
344 XftFont *pub,
345 FcBool need_bitmaps,
346 _Xconstconst FT_UInt *glyphs,
347 int nglyph)
348{
349 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
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_RGB1:
381 case FC_RGBA_BGR2:
382 mode = FT_RENDER_MODE_LCD;
383 break;
384 case FC_RGBA_VRGB3:
385 case FC_RGBA_VBGR4:
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_CACHE128)
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_BITMAP0x8)
422 error = FT_Load_Glyph (face, glyphindex,
423 font->info.load_flags & ~FT_LOAD_NO_BITMAP0x8);
424 if (error)
425 continue;
426 }
427
428#define FLOOR(x)((x) & -64) ((x) & -64)
429#define CEIL(x)(((x)+63) & -64) (((x)+63) & -64)
430#define TRUNC(x)((x) >> 6) ((x) >> 6)
431#define ROUND(x)(((x)+32) & -64) (((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_GLYPH32)
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 = vector.x;
460 top = bottom = vector.y;
461 } else {
462 if(left > vector.x) left = vector.x;
463 if(right < vector.x) right = vector.x;
464 if(bottom > vector.y) bottom = vector.y;
465 if(top < vector.y) top = vector.y;
466 }
467
468 }
469 }
470 left = FLOOR(left)((left) & -64);
471 right = CEIL(right)(((right)+63) & -64);
472 bottom = FLOOR(bottom)((bottom) & -64);
473 top = CEIL(top)(((top)+63) & -64);
474
475 } else {
476 left = FLOOR( glyphslot->metrics.horiBearingX )((glyphslot->metrics.horiBearingX) & -64);
477 right = CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width )(((glyphslot->metrics.horiBearingX + glyphslot->metrics
.width)+63) & -64)
;
478
479 top = CEIL( glyphslot->metrics.horiBearingY )(((glyphslot->metrics.horiBearingY)+63) & -64);
480 bottom = FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height )((glyphslot->metrics.horiBearingY - glyphslot->metrics.
height) & -64)
;
481 }
482
483 width = TRUNC(right - left)((right - left) >> 6);
484 height = TRUNC( top - bottom )((top - bottom) >> 6);
485
486 /*
487 * Clip charcell glyphs to the bounding box
488 * XXX transformed?
489 */
490 if (font->info.spacing >= FC_CHARCELL110 && !font->info.transform)
491 {
492 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT0x10)
493 {
494 if (TRUNC(bottom)((bottom) >> 6) > 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;
Value stored to 'height' is never read
504 }
505 }
506 else
507 {
508 if (TRUNC(right)((right) >> 6) > 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_MONO100)
532 {
533 if (font->info.transform)
534 {
535 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT0x10)
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 = vector.x >> 6;
547 xftg->metrics.yOff = -(vector.y >> 6);
548 }
549 else
550 {
551 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT0x10)
552 {
553 xftg->metrics.xOff = 0;
554 xftg->metrics.yOff = -font->public.max_advance_width;
555 }
556 else
557 {
558 xftg->metrics.xOff = font->public.max_advance_width;
559 xftg->metrics.yOff = 0;
560 }
561 }
562 }
563 else
564 {
565 xftg->metrics.xOff = TRUNC(ROUND(glyphslot->advance.x))(((((glyphslot->advance.x)+32) & -64)) >> 6);
566 xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y))(((((glyphslot->advance.y)+32) & -64)) >> 6);
567 }
568
569 // compute the size of the final bitmap
570 ftbit = &glyphslot->bitmap;
571
572 width = ftbit->width;
573 height = ftbit->rows;
574
575 if (XftDebug() & XFT_DBG_GLYPH32)
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_GLYPHV64)
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 = local.width;
621 xftg->metrics.height = local.rows;
622 xftg->metrics.x = - glyphslot->bitmap_left;
623 xftg->metrics.y = 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);
640 if (!bufBitmap)
641 continue;
642 bufSize = size;
643 }
644 memset (bufBitmap, 0, size);
645
646 local.buffer = bufBitmap;
647
648 _fill_xrender_bitmap( &local, glyphslot, mode,
649 (font->info.rgba == FC_RGBA_BGR2 ||
650 font->info.rgba == FC_RGBA_VBGR4 ) );
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 + 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)(((_XPrivDisplay)dpy)->bitmap_bit_order) != MSBFirst1)
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++ = c;
685 }
686 }
687 }
688 else if ( mode != FT_RENDER_MODE_NORMAL )
689 {
690 /* invert ARGB <=> BGRA */
691 if (ImageByteOrder (dpy)(((_XPrivDisplay)dpy)->byte_order) != 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);
703 if (xftg->bitmap)
704 memcpy (xftg->bitmap, bufBitmap, size);
705 }
706 else
707 xftg->bitmap = NULL((void*)0);
708 }
709
710 font->glyph_memory += xftg->glyph_memory;
711 info->glyph_memory += xftg->glyph_memory;
712 if (XftDebug() & XFT_DBG_CACHE128)
713 _XftFontValidateMemory (dpy, pub);
714 if (XftDebug() & XFT_DBG_CACHEV256)
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__attribute__((visibility("default"))) void
724XftFontUnloadGlyphs (Display *dpy,
725 XftFont *pub,
726 _Xconstconst FT_UInt *glyphs,
727 int nglyph)
728{
729 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0);
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_GLYPH3, sizeof (XftGlyph));
768 font->glyphs[glyphindex] = NULL((void*)0);
769 }
770 if (font->glyphset && nused)
771 XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
772}
773
774_X_EXPORT__attribute__((visibility("default"))) FcBool
775XftFontCheckGlyph (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 FcFalse0;
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 FcFalse0;
796 XftMemAlloc (XFT_MEM_GLYPH3, sizeof (XftGlyph));
797 xftg->bitmap = NULL((void*)0);
798 xftg->glyph_memory = 0;
799 font->glyphs[glyph] = xftg;
800 }
801 n = *nmissing;
802 missing[n++] = glyph;
803 if (n == XFT_NMISSING256)
804 {
805 XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
806 n = 0;
807 }
808 *nmissing = n;
809 return FcTrue1;
810 }
811 else
812 return FcFalse0;
813}
814
815_X_EXPORT__attribute__((visibility("default"))) FcBool
816XftCharExists (Display *dpy,
817 XftFont *pub,
818 FcChar32 ucs4)
819{
820 if (pub->charset)
821 return FcCharSetHasChar (pub->charset, ucs4);
822 return FcFalse0;
823}
824
825#define Missing((FT_UInt) ~0) ((FT_UInt) ~0)
826
827_X_EXPORT__attribute__((visibility("default"))) FT_UInt
828XftCharIndex (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 % 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 % font->rehash_value;
858 if (!offset)
859 offset = 1;
860 }
861 ent = ent + offset;
862 if (ent >= font->hash_value)
863 ent -= 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__attribute__((visibility("hidden"))) void
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 = 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_CACHE128)
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_CACHEV256)
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_CACHE128)
916 _XftFontValidateMemory (dpy, pub);
917}
918
919_X_HIDDEN__attribute__((visibility("hidden"))) void
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_CACHE128)
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}