Bug Summary

File:xftfreetype.c
Location:line 863, column 2
Description:Value stored to 'num_unicode' 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
25_X_HIDDEN__attribute__((visibility("hidden"))) FT_Library _XftFTlibrary;
26
27#define FT_Matrix_Equal(a,b)((a)->xx == (b)->xx && (a)->yy == (b)->yy
&& (a)->xy == (b)->xy && (a)->yx ==
(b)->yx)
((a)->xx == (b)->xx && \
28 (a)->yy == (b)->yy && \
29 (a)->xy == (b)->xy && \
30 (a)->yx == (b)->yx)
31/*
32 * List of all open files (each face in a file is managed separately)
33 */
34
35static XftFtFile *_XftFtFiles;
36static int XftMaxFreeTypeFiles = 5;
37
38static XftFtFile *
39_XftGetFile (const FcChar8 *file, int id)
40{
41 XftFtFile *f;
42
43 if (!XftInitFtLibrary ())
44 return NULL((void*)0);
45
46 for (f = _XftFtFiles; f; f = f->next)
47 {
48 if (!strcmp (f->file, (char *) file) && f->id == id)
49 {
50 ++f->ref;
51 if (XftDebug () & XFT_DBG_REF16)
52 printf ("FontFile %s/%d matches existing (%d)\n",
53 file, id, f->ref);
54 return f;
55 }
56 }
57 f = malloc (sizeof (XftFtFile) + strlen ((char *) file) + 1);
58 if (!f)
59 return NULL((void*)0);
60
61 XftMemAlloc (XFT_MEM_FILE2, sizeof (XftFtFile) + strlen ((char *) file) + 1);
62 if (XftDebug () & XFT_DBG_REF16)
63 printf ("FontFile %s/%d matches new\n",
64 file, id);
65 f->next = _XftFtFiles;
66 _XftFtFiles = f;
67
68 f->ref = 1;
69
70 f->file = (char *) (f+1);
71 strcpy (f->file, (char *) file);
72 f->id = id;
73
74 f->lock = 0;
75 f->face = NULL((void*)0);
76 f->xsize = 0;
77 f->ysize = 0;
78 f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
79 return f;
80}
81
82static XftFtFile *
83_XftGetFaceFile (FT_Face face)
84{
85 XftFtFile *f;
86
87 f = malloc (sizeof (XftFtFile));
88 if (!f)
89 return NULL((void*)0);
90 XftMemAlloc (XFT_MEM_FILE2, sizeof(XftFtFile));
91 f->next = NULL((void*)0);
92
93 f->ref = 1;
94
95 f->file = NULL((void*)0);
96 f->id = 0;
97 f->lock = 0;
98 f->face = face;
99 f->xsize = 0;
100 f->ysize = 0;
101 f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
102 return f;
103}
104
105static int
106_XftNumFiles (void)
107{
108 XftFtFile *f;
109 int count = 0;
110 for (f = _XftFtFiles; f; f = f->next)
111 if (f->face && !f->lock)
112 ++count;
113 return count;
114}
115
116static XftFtFile *
117_XftNthFile (int n)
118{
119 XftFtFile *f;
120 int count = 0;
121 for (f = _XftFtFiles; f; f = f->next)
122 if (f->face && !f->lock)
123 if (count++ == n)
124 break;
125 return f;
126}
127
128static void
129_XftUncacheFiles (void)
130{
131 int n;
132 XftFtFile *f;
133 while ((n = _XftNumFiles ()) > XftMaxFreeTypeFiles)
134 {
135 f = _XftNthFile (rand () % n);
136 if (f)
137 {
138 if (XftDebug() & XFT_DBG_REF16)
139 printf ("Discard file %s/%d from cache\n",
140 f->file, f->id);
141 FT_Done_Face (f->face);
142 f->face = NULL((void*)0);
143 }
144 }
145}
146
147static FT_Face
148_XftLockFile (XftFtFile *f)
149{
150 ++f->lock;
151 if (!f->face)
152 {
153 if (XftDebug() & XFT_DBG_REF16)
154 printf ("Loading file %s/%d\n", f->file, f->id);
155 if (FT_New_Face (_XftFTlibrary, f->file, f->id, &f->face))
156 --f->lock;
157
158 f->xsize = 0;
159 f->ysize = 0;
160 f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
161 _XftUncacheFiles ();
162 }
163 return f->face;
164}
165
166static void
167_XftLockError (const char *reason)
168{
169 fprintf (stderrstderr, "Xft: locking error %s\n", reason);
170}
171
172static void
173_XftUnlockFile (XftFtFile *f)
174{
175 if (--f->lock < 0)
176 _XftLockError ("too many file unlocks");
177}
178
179#define X_SIZE(face,i)((face)->available_sizes[i].x_ppem) ((face)->available_sizes[i].x_ppem)
180#define Y_SIZE(face,i)((face)->available_sizes[i].y_ppem) ((face)->available_sizes[i].y_ppem)
181
182_X_HIDDEN__attribute__((visibility("hidden"))) FcBool
183_XftSetFace (XftFtFile *f, FT_F26Dot6 xsize, FT_F26Dot6 ysize, FT_Matrix *matrix)
184{
185 FT_Face face = f->face;
186
187 if (f->xsize != xsize || f->ysize != ysize)
188 {
189 if (XftDebug() & XFT_DBG_GLYPH32)
190 printf ("Set face size to %dx%d (%dx%d)\n",
191 (int) (xsize >> 6), (int) (ysize >> 6), (int) xsize, (int) ysize);
192 /*
193 * Bitmap only faces must match exactly, so find the closest
194 * one (height dominant search)
195 */
196 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )))
197 {
198 int i, best = 0;
199
200#define xft_abs(a)((a) < 0 ? -(a) : (a)) ((a) < 0 ? -(a) : (a))
201#define dist(a,b)((((a)-(b)) < 0 ? -((a)-(b)) : ((a)-(b)))) (xft_abs((a)-(b))(((a)-(b)) < 0 ? -((a)-(b)) : ((a)-(b))))
202
203 for (i = 1; i < face->num_fixed_sizes; i++)
204 {
205 if (dist (ysize, Y_SIZE(face,i))((((ysize)-(((face)->available_sizes[i].y_ppem))) < 0 ?
-((ysize)-(((face)->available_sizes[i].y_ppem))) : ((ysize
)-(((face)->available_sizes[i].y_ppem)))))
<
206 dist (ysize, Y_SIZE(face, best))((((ysize)-(((face)->available_sizes[best].y_ppem))) < 0
? -((ysize)-(((face)->available_sizes[best].y_ppem))) : (
(ysize)-(((face)->available_sizes[best].y_ppem)))))
||
207 (dist (ysize, Y_SIZE(face, i))((((ysize)-(((face)->available_sizes[i].y_ppem))) < 0 ?
-((ysize)-(((face)->available_sizes[i].y_ppem))) : ((ysize
)-(((face)->available_sizes[i].y_ppem)))))
==
208 dist (ysize, Y_SIZE(face, best))((((ysize)-(((face)->available_sizes[best].y_ppem))) < 0
? -((ysize)-(((face)->available_sizes[best].y_ppem))) : (
(ysize)-(((face)->available_sizes[best].y_ppem)))))
&&
209 dist (xsize, X_SIZE(face, i))((((xsize)-(((face)->available_sizes[i].x_ppem))) < 0 ?
-((xsize)-(((face)->available_sizes[i].x_ppem))) : ((xsize
)-(((face)->available_sizes[i].x_ppem)))))
<
210 dist (xsize, X_SIZE(face, best))((((xsize)-(((face)->available_sizes[best].x_ppem))) < 0
? -((xsize)-(((face)->available_sizes[best].x_ppem))) : (
(xsize)-(((face)->available_sizes[best].x_ppem)))))
))
211 {
212 best = i;
213 }
214 }
215 /*
216 * Freetype 2.1.7 and earlier used width/height
217 * for matching sizes in the BDF and PCF loaders.
218 * This has been fixed for 2.1.8. Because BDF and PCF
219 * files have but a single strike per file, we can
220 * simply try both sizes.
221 */
222 if (FT_Set_Char_Size (face, face->available_sizes[best].x_ppem,
223 face->available_sizes[best].y_ppem, 0, 0) != 0
224 &&
225 FT_Set_Char_Size (face, face->available_sizes[best].width << 6,
226 face->available_sizes[best].height << 6,
227 0, 0) != 0)
228 {
229 return False0;
230 }
231 }
232 else
233 {
234 if (FT_Set_Char_Size (face, xsize, ysize, 0, 0))
235 {
236 return False0;
237 }
238 }
239 f->xsize = xsize;
240 f->ysize = ysize;
241 }
242 if (!FT_Matrix_Equal (&f->matrix, matrix)((&f->matrix)->xx == (matrix)->xx && (&
f->matrix)->yy == (matrix)->yy && (&f->
matrix)->xy == (matrix)->xy && (&f->matrix
)->yx == (matrix)->yx)
)
243 {
244 if (XftDebug() & XFT_DBG_GLYPH32)
245 printf ("Set face matrix to (%g,%g,%g,%g)\n",
246 (double) matrix->xx / 0x10000,
247 (double) matrix->xy / 0x10000,
248 (double) matrix->yx / 0x10000,
249 (double) matrix->yy / 0x10000);
250 FT_Set_Transform (face, matrix, NULL((void*)0));
251 f->matrix = *matrix;
252 }
253 return True1;
254}
255
256static void
257_XftReleaseFile (XftFtFile *f)
258{
259 XftFtFile **prev;
260
261 if (--f->ref != 0)
262 return;
263 if (f->lock)
264 _XftLockError ("Attempt to close locked file");
265 if (f->file)
266 {
267 for (prev = &_XftFtFiles; *prev; prev = &(*prev)->next)
268 {
269 if (*prev == f)
270 {
271 *prev = f->next;
272 break;
273 }
274 }
275 if (f->face)
276 FT_Done_Face (f->face);
277 }
278 XftMemFree (XFT_MEM_FILE2,
279 sizeof (XftFtFile) + (f->file ? strlen (f->file) + 1 : 0));
280 free (f);
281}
282
283/*
284 * Find a prime larger than the minimum reasonable hash size
285 */
286
287static FcChar32
288_XftSqrt (FcChar32 a)
289{
290 FcChar32 l, h, m;
291
292 l = 2;
293 h = a/2;
294 while ((h-l) > 1)
295 {
296 m = (h+l) >> 1;
297 if (m * m < a)
298 l = m;
299 else
300 h = m;
301 }
302 return h;
303}
304
305static FcBool
306_XftIsPrime (FcChar32 i)
307{
308 FcChar32 l, t;
309
310 if (i < 2)
311 return FcFalse0;
312 if ((i & 1) == 0)
313 {
314 if (i == 2)
315 return FcTrue1;
316 return FcFalse0;
317 }
318 l = _XftSqrt (i) + 1;
319 for (t = 3; t <= l; t += 2)
320 if (i % t == 0)
321 return FcFalse0;
322 return FcTrue1;
323}
324
325static FcChar32
326_XftHashSize (FcChar32 num_unicode)
327{
328 /* at least 31.25 % extra space */
329 FcChar32 hash = num_unicode + (num_unicode >> 2) + (num_unicode >> 4);
330
331 if ((hash & 1) == 0)
332 hash++;
333 while (!_XftIsPrime (hash))
334 hash += 2;
335 return hash;
336}
337
338_X_EXPORT__attribute__((visibility("default"))) FT_Face
339XftLockFace (XftFont *public)
340{
341 XftFontInt *font = (XftFontInt *) public;
342 XftFontInfo *fi = &font->info;
343 FT_Face face;
344
345 face = _XftLockFile (fi->file);
346 /*
347 * Make sure the face is usable at the requested size
348 */
349 if (face && !_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix))
350 {
351 _XftUnlockFile (fi->file);
352 face = NULL((void*)0);
353 }
354 return face;
355}
356
357_X_EXPORT__attribute__((visibility("default"))) void
358XftUnlockFace (XftFont *public)
359{
360 XftFontInt *font = (XftFontInt *) public;
361 _XftUnlockFile (font->info.file);
362}
363
364static FcBool
365XftFontInfoFill (Display *dpy, _Xconstconst FcPattern *pattern, XftFontInfo *fi)
366{
367 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
368 FcChar8 *filename;
369 int id;
370 double dsize;
371 double aspect;
372 FcMatrix *font_matrix;
373 FcBool hinting, vertical_layout, autohint, global_advance;
374 int hint_style;
375 FcChar32 hash, *hashp;
376 FT_Face face;
377 int nhash;
378 FcBool bitmap;
379
380 if (!info)
381 return FcFalse0;
382
383 /*
384 * Initialize the whole XftFontInfo so that padding doesn't interfere with
385 * hash or XftFontInfoEqual().
386 */
387
388 memset (fi, '\0', sizeof(*fi));
389
390 /*
391 * Find the associated file
392 */
393 switch (FcPatternGetString (pattern, FC_FILE"file", 0, &filename)) {
394 case FcResultNoMatch:
395 filename = NULL((void*)0);
396 break;
397 case FcResultMatch:
398 break;
399 default:
400 goto bail0;
401 }
402
403 switch (FcPatternGetInteger (pattern, FC_INDEX"index", 0, &id)) {
404 case FcResultNoMatch:
405 id = 0;
406 break;
407 case FcResultMatch:
408 break;
409 default:
410 goto bail0;
411 }
412
413 if (filename)
414 fi->file = _XftGetFile (filename, id);
415 else if (FcPatternGetFTFace (pattern, FC_FT_FACE"ftface", 0, &face) == FcResultMatch
416 && face)
417 fi->file = _XftGetFaceFile (face);
418 if (!fi->file)
419 goto bail0;
420
421 /*
422 * Compute pixel size
423 */
424 if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE"pixelsize", 0, &dsize) != FcResultMatch)
425 goto bail1;
426
427 if (FcPatternGetDouble (pattern, FC_ASPECT"aspect", 0, &aspect) != FcResultMatch)
428 aspect = 1.0;
429
430 fi->ysize = (FT_F26Dot6) (dsize * 64.0);
431 fi->xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
432
433 if (XftDebug() & XFT_DBG_OPEN1)
434 printf ("XftFontInfoFill: %s: %d (%g pixels)\n",
435 (filename ? filename : (FcChar8 *) "<none>"), id, dsize);
436 /*
437 * Get antialias value
438 */
439 switch (FcPatternGetBool (pattern, FC_ANTIALIAS"antialias", 0, &fi->antialias)) {
440 case FcResultNoMatch:
441 fi->antialias = True1;
442 break;
443 case FcResultMatch:
444 break;
445 default:
446 goto bail1;
447 }
448
449 /*
450 * Get rgba value
451 */
452 switch (FcPatternGetInteger (pattern, FC_RGBA"rgba", 0, &fi->rgba)) {
453 case FcResultNoMatch:
454 fi->rgba = FC_RGBA_UNKNOWN0;
455 break;
456 case FcResultMatch:
457 break;
458 default:
459 goto bail1;
460 }
461
462 /*
463 * Get lcd_filter value
464 */
465 switch (FcPatternGetInteger (pattern, FC_LCD_FILTER"lcdfilter", 0, &fi->lcd_filter)) {
466 case FcResultNoMatch:
467 fi->lcd_filter = FC_LCD_DEFAULT1;
468 break;
469 case FcResultMatch:
470 break;
471 default:
472 goto bail1;
473 }
474
475 /*
476 * Get matrix and transform values
477 */
478 switch (FcPatternGetMatrix (pattern, FC_MATRIX"matrix", 0, &font_matrix)) {
479 case FcResultNoMatch:
480 fi->matrix.xx = fi->matrix.yy = 0x10000;
481 fi->matrix.xy = fi->matrix.yx = 0;
482 break;
483 case FcResultMatch:
484 fi->matrix.xx = 0x10000L * font_matrix->xx;
485 fi->matrix.yy = 0x10000L * font_matrix->yy;
486 fi->matrix.xy = 0x10000L * font_matrix->xy;
487 fi->matrix.yx = 0x10000L * font_matrix->yx;
488 break;
489 default:
490 goto bail1;
491 }
492
493 fi->transform = (fi->matrix.xx != 0x10000 || fi->matrix.xy != 0 ||
494 fi->matrix.yx != 0 || fi->matrix.yy != 0x10000);
495
496 /*
497 * Get render value, set to false if no Render extension present
498 */
499 if (info->hasRender)
500 {
501 switch (FcPatternGetBool (pattern, XFT_RENDER"render", 0, &fi->render)) {
502 case FcResultNoMatch:
503 fi->render = info->hasRender;
504 break;
505 case FcResultMatch:
506 break;
507 default:
508 goto bail1;
509 }
510 }
511 else
512 fi->render = FcFalse0;
513
514 /*
515 * Compute glyph load flags
516 */
517 fi->load_flags = FT_LOAD_DEFAULT0x0;
518
519#ifndef XFT_EMBEDDED_BITMAP"embeddedbitmap"
520#define XFT_EMBEDDED_BITMAP"embeddedbitmap" "embeddedbitmap"
521#endif
522
523 switch (FcPatternGetBool (pattern, XFT_EMBEDDED_BITMAP"embeddedbitmap", 0, &bitmap)) {
524 case FcResultNoMatch:
525 bitmap = FcFalse0;
526 break;
527 case FcResultMatch:
528 break;
529 default:
530 goto bail1;
531 }
532
533 /* disable bitmaps when anti-aliasing or transforming glyphs */
534 if ((!bitmap && fi->antialias) || fi->transform)
535 fi->load_flags |= FT_LOAD_NO_BITMAP( 1L << 3 );
536
537 /* disable hinting if requested */
538 switch (FcPatternGetBool (pattern, FC_HINTING"hinting", 0, &hinting)) {
539 case FcResultNoMatch:
540 hinting = FcTrue1;
541 break;
542 case FcResultMatch:
543 break;
544 default:
545 goto bail1;
546 }
547
548 switch (FcPatternGetBool (pattern, FC_EMBOLDEN"embolden", 0, &fi->embolden)) {
549 case FcResultNoMatch:
550 fi->embolden = FcFalse0;
551 break;
552 case FcResultMatch:
553 break;
554 default:
555 goto bail1;
556 }
557
558 switch (FcPatternGetInteger (pattern, FC_HINT_STYLE"hintstyle", 0, &hint_style)) {
559 case FcResultNoMatch:
560 hint_style = FC_HINT_FULL3;
561 break;
562 case FcResultMatch:
563 break;
564 default:
565 goto bail1;
566 }
567
568 if (!hinting
569 || hint_style == FC_HINT_NONE0
570 )
571 {
572 fi->load_flags |= FT_LOAD_NO_HINTING( 1L << 1 );
573 }
574
575 /* Figure out the load target, which modifies the hinting
576 * behavior of FreeType based on the intended use of the glyphs.
577 */
578 if (fi->antialias)
579 {
580 if (FC_HINT_NONE0 < hint_style && hint_style < FC_HINT_FULL3)
581 {
582 fi->load_flags |= FT_LOAD_TARGET_LIGHT( (FT_Int32)( (FT_RENDER_MODE_LIGHT) & 15 ) << 16 );
583 }
584 else
585 {
586 /* autohinter will snap stems to integer widths, when
587 * the LCD targets are used.
588 */
589 switch (fi->rgba) {
590 case FC_RGBA_RGB1:
591 case FC_RGBA_BGR2:
592 fi->load_flags |= FT_LOAD_TARGET_LCD( (FT_Int32)( (FT_RENDER_MODE_LCD) & 15 ) << 16 );
593 break;
594 case FC_RGBA_VRGB3:
595 case FC_RGBA_VBGR4:
596 fi->load_flags |= FT_LOAD_TARGET_LCD_V( (FT_Int32)( (FT_RENDER_MODE_LCD_V) & 15 ) << 16 );
597 break;
598 }
599 }
600 }
601 else
602 fi->load_flags |= FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 );
603
604 /* set vertical layout if requested */
605 switch (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT"verticallayout", 0, &vertical_layout)) {
606 case FcResultNoMatch:
607 vertical_layout = FcFalse0;
608 break;
609 case FcResultMatch:
610 break;
611 default:
612 goto bail1;
613 }
614
615 if (vertical_layout)
616 fi->load_flags |= FT_LOAD_VERTICAL_LAYOUT( 1L << 4 );
617
618 /* force autohinting if requested */
619 switch (FcPatternGetBool (pattern, FC_AUTOHINT"autohint", 0, &autohint)) {
620 case FcResultNoMatch:
621 autohint = FcFalse0;
622 break;
623 case FcResultMatch:
624 break;
625 default:
626 goto bail1;
627 }
628
629 if (autohint)
630 fi->load_flags |= FT_LOAD_FORCE_AUTOHINT( 1L << 5 );
631
632 /* disable global advance width (for broken DynaLab TT CJK fonts) */
633 switch (FcPatternGetBool (pattern, FC_GLOBAL_ADVANCE"globaladvance", 0, &global_advance)) {
634 case FcResultNoMatch:
635 global_advance = FcTrue1;
636 break;
637 case FcResultMatch:
638 break;
639 default:
640 goto bail1;
641 }
642
643 if (!global_advance)
644 fi->load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH( 1L << 9 );
645
646 /*
647 * Get requested spacing value
648 */
649 switch (FcPatternGetInteger (pattern, FC_SPACING"spacing", 0, &fi->spacing)) {
650 case FcResultNoMatch:
651 fi->spacing = FC_PROPORTIONAL0;
652 break;
653 case FcResultMatch:
654 break;
655 default:
656 goto bail1;
657 }
658
659 /*
660 * Check for minspace
661 */
662
663 switch (FcPatternGetBool (pattern, FC_MINSPACE"minspace", 0, &fi->minspace)) {
664 case FcResultNoMatch:
665 fi->minspace = FcFalse0;
666 break;
667 case FcResultMatch:
668 break;
669 default:
670 goto bail1;
671 }
672 /*
673 * Check for fixed pixel spacing
674 */
675 switch (FcPatternGetInteger (pattern, FC_CHAR_WIDTH"charwidth", 0, &fi->char_width)) {
676 case FcResultNoMatch:
677 fi->char_width = 0;
678 break;
679 case FcResultMatch:
680 if (fi->char_width)
681 fi->spacing = FC_MONO100;
682 break;
683 default:
684 goto bail1;
685 }
686
687 /*
688 * Step over hash value in the structure
689 */
690 hash = 0;
691 hashp = (FcChar32 *) fi + 1;
692 nhash = (sizeof (XftFontInfo) / sizeof (FcChar32)) - 1;
693
694 while (nhash--)
695 hash += *hashp++;
696 fi->hash = hash;
697
698 /*
699 * All done
700 */
701 return FcTrue1;
702
703bail1:
704 _XftReleaseFile (fi->file);
705 fi->file = NULL((void*)0);
706bail0:
707 return FcFalse0;
708}
709
710static void
711XftFontInfoEmpty (Display *dpy, XftFontInfo *fi)
712{
713 if (fi->file)
714 _XftReleaseFile (fi->file);
715}
716
717XftFontInfo *
718XftFontInfoCreate (Display *dpy, _Xconstconst FcPattern *pattern)
719{
720 XftFontInfo *fi = malloc (sizeof (XftFontInfo));
721
722 if (!fi)
723 return NULL((void*)0);
724
725 if (!XftFontInfoFill (dpy, pattern, fi))
726 {
727 free (fi);
728 fi = NULL((void*)0);
729 }
730 XftMemAlloc (XFT_MEM_FONT1, sizeof (XftFontInfo));
731 return fi;
732}
733
734_X_EXPORT__attribute__((visibility("default"))) void
735XftFontInfoDestroy (Display *dpy, XftFontInfo *fi)
736{
737 XftFontInfoEmpty (dpy, fi);
738 XftMemFree (XFT_MEM_FONT1, sizeof (XftFontInfo));
739 free (fi);
740}
741
742_X_EXPORT__attribute__((visibility("default"))) FcChar32
743XftFontInfoHash (_Xconstconst XftFontInfo *fi)
744{
745 return fi->hash;
746}
747
748_X_EXPORT__attribute__((visibility("default"))) FcBool
749XftFontInfoEqual (_Xconstconst XftFontInfo *a, _Xconstconst XftFontInfo *b)
750{
751 return memcmp ((void *) a, (void *) b, sizeof (XftFontInfo)) == 0;
752}
753
754_X_EXPORT__attribute__((visibility("default"))) XftFont *
755XftFontOpenInfo (Display *dpy,
756 FcPattern *pattern,
757 XftFontInfo *fi)
758{
759 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
760 FT_Face face;
761 XftFont **bucket;
762 XftFontInt *font;
763 XRenderPictFormat *format;
764 FcCharSet *charset;
765 FcChar32 num_unicode;
766 FcChar32 hash_value;
767 FcChar32 rehash_value;
768 FcBool antialias;
769 int max_glyph_memory;
770 int alloc_size;
771 int ascent, descent, height;
772 int i;
773 int num_glyphs;
774
775 if (!info)
776 return NULL((void*)0);
777 /*
778 * Find a matching previously opened font
779 */
780 bucket = &info->fontHash[fi->hash % XFT_NUM_FONT_HASH127];
781 for (font = (XftFontInt *) *bucket; font; font = (XftFontInt *) font->hash_next)
782 if (XftFontInfoEqual (&font->info, fi))
783 {
784 if (!font->ref++)
785 --info->num_unref_fonts;
786 FcPatternDestroy (pattern);
787 return &font->public;
788 }
789
790 /*
791 * No existing font, create another.
792 */
793
794 if (XftDebug () & XFT_DBG_CACHE128)
795 printf ("New font %s/%d size %dx%d\n",
796 fi->file->file, fi->file->id,
797 (int) fi->xsize >> 6, (int) fi->ysize >> 6);
798
799 if (FcPatternGetInteger (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0,
800 &max_glyph_memory) != FcResultMatch)
801 max_glyph_memory = XFT_FONT_MAX_GLYPH_MEMORY(1024 * 1024);
802
803 face = _XftLockFile (fi->file);
804 if (!face)
805 goto bail0;
806
807 if (!_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix))
808 goto bail1;
809
810 /*
811 * Get the set of Unicode codepoints covered by the font.
812 * If the incoming pattern doesn't provide this data, go
813 * off and compute it. Yes, this is expensive, but it's
814 * required to map Unicode to glyph indices.
815 */
816 if (FcPatternGetCharSet (pattern, FC_CHARSET"charset", 0, &charset) == FcResultMatch)
817 charset = FcCharSetCopy (charset);
818 else
819 charset = FcFreeTypeCharSet (face, FcConfigGetBlanks (NULL((void*)0)));
820
821 antialias = fi->antialias;
822 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )))
823 antialias = FcFalse0;
824
825 /*
826 * Find the appropriate picture format
827 */
828 if (fi->render)
829 {
830 if (antialias)
831 {
832 switch (fi->rgba) {
833 case FC_RGBA_RGB1:
834 case FC_RGBA_BGR2:
835 case FC_RGBA_VRGB3:
836 case FC_RGBA_VBGR4:
837 format = XRenderFindStandardFormat (dpy, PictStandardARGB320);
838 break;
839 default:
840 format = XRenderFindStandardFormat (dpy, PictStandardA82);
841 break;
842 }
843 }
844 else
845 {
846 format = XRenderFindStandardFormat (dpy, PictStandardA14);
847 }
848
849 if (!format)
850 goto bail2;
851 }
852 else
853 format = NULL((void*)0);
854
855 if (charset)
856 {
857 num_unicode = FcCharSetCount (charset);
858 hash_value = _XftHashSize (num_unicode);
859 rehash_value = hash_value - 2;
860 }
861 else
862 {
863 num_unicode = 0;
Value stored to 'num_unicode' is never read
864 hash_value = 0;
865 rehash_value = 0;
866 }
867
868 /*
869 * Sometimes the glyphs are numbered 1..n, other times 0..n-1,
870 * accept either numbering scheme by making room in the table
871 */
872 num_glyphs = face->num_glyphs + 1;
873 alloc_size = (sizeof (XftFontInt) +
874 num_glyphs * sizeof (XftGlyph *) +
875 hash_value * sizeof (XftUcsHash));
876 font = malloc (alloc_size);
877
878 if (!font)
879 goto bail2;
880
881 XftMemAlloc (XFT_MEM_FONT1, alloc_size);
882
883 /*
884 * Public fields
885 */
886 if (fi->transform)
887 {
888 FT_Vector vector;
889
890 vector.x = 0;
891 vector.y = face->size->metrics.descender;
892 FT_Vector_Transform (&vector, &fi->matrix);
893 descent = -(vector.y >> 6);
894
895 vector.x = 0;
896 vector.y = face->size->metrics.ascender;
897 FT_Vector_Transform (&vector, &fi->matrix);
898 ascent = vector.y >> 6;
899
900 if (fi->minspace)
901 height = ascent + descent;
902 else
903 {
904 vector.x = 0;
905 vector.y = face->size->metrics.height;
906 FT_Vector_Transform (&vector, &fi->matrix);
907 height = vector.y >> 6;
908 }
909 }
910 else
911 {
912 descent = -(face->size->metrics.descender >> 6);
913 ascent = face->size->metrics.ascender >> 6;
914 if (fi->minspace)
915 height = ascent + descent;
916 else
917 height = face->size->metrics.height >> 6;
918 }
919 font->public.ascent = ascent;
920 font->public.descent = descent;
921 font->public.height = height;
922
923 if (fi->char_width)
924 font->public.max_advance_width = fi->char_width;
925 else
926 {
927 if (fi->transform)
928 {
929 FT_Vector vector;
930 vector.x = face->size->metrics.max_advance;
931 vector.y = 0;
932 FT_Vector_Transform (&vector, &fi->matrix);
933 font->public.max_advance_width = vector.x >> 6;
934 }
935 else
936 font->public.max_advance_width = face->size->metrics.max_advance >> 6;
937 }
938 font->public.charset = charset;
939 font->public.pattern = pattern;
940
941 /*
942 * Management fields
943 */
944 font->ref = 1;
945
946 font->next = info->fonts;
947 info->fonts = &font->public;
948
949 font->hash_next = *bucket;
950 *bucket = &font->public;
951
952 /*
953 * Copy the info over
954 */
955 font->info = *fi;
956 /*
957 * reset the antialias field. It can't
958 * be set correctly until the font is opened,
959 * which doesn't happen in XftFontInfoFill
960 */
961 font->info.antialias = antialias;
962 /*
963 * bump XftFile reference count
964 */
965 font->info.file->ref++;
966
967 /*
968 * Per glyph information
969 */
970 font->glyphs = (XftGlyph **) (font + 1);
971 memset (font->glyphs, '\0', num_glyphs * sizeof (XftGlyph *));
972 font->num_glyphs = num_glyphs;
973 /*
974 * Unicode hash table information
975 */
976 font->hash_table = (XftUcsHash *) (font->glyphs + font->num_glyphs);
977 for (i = 0; i < hash_value; i++)
978 {
979 font->hash_table[i].ucs4 = ((FcChar32) ~0);
980 font->hash_table[i].glyph = 0;
981 }
982 font->hash_value = hash_value;
983 font->rehash_value = rehash_value;
984 /*
985 * X specific fields
986 */
987 font->glyphset = 0;
988 font->format = format;
989
990 /*
991 * Glyph memory management fields
992 */
993 font->glyph_memory = 0;
994 font->max_glyph_memory = max_glyph_memory;
995 font->use_free_glyphs = info->use_free_glyphs;
996
997 _XftUnlockFile (fi->file);
998
999 return &font->public;
1000
1001bail2:
1002 FcCharSetDestroy (charset);
1003bail1:
1004 _XftUnlockFile (fi->file);
1005bail0:
1006 return NULL((void*)0);
1007}
1008
1009_X_EXPORT__attribute__((visibility("default"))) XftFont *
1010XftFontOpenPattern (Display *dpy, FcPattern *pattern)
1011{
1012 XftFontInfo info;
1013 XftFont *font;
1014
1015 if (!XftFontInfoFill (dpy, pattern, &info))
1016 return NULL((void*)0);
1017
1018 font = XftFontOpenInfo (dpy, pattern, &info);
1019 XftFontInfoEmpty (dpy, &info);
1020 return font;
1021}
1022
1023_X_EXPORT__attribute__((visibility("default"))) XftFont *
1024XftFontCopy (Display *dpy, XftFont *public)
1025{
1026 XftFontInt *font = (XftFontInt *) public;
1027
1028 font->ref++;
1029 return public;
1030}
1031
1032static void
1033XftFontDestroy (Display *dpy, XftFont *public)
1034{
1035 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0);
1036 XftFontInt *font = (XftFontInt *) public;
1037 int i;
1038
1039 /* note reduction in memory use */
1040 if (info)
1041 info->glyph_memory -= font->glyph_memory;
1042 /* Clean up the info */
1043 XftFontInfoEmpty (dpy, &font->info);
1044 /* Free the glyphset */
1045 if (font->glyphset)
1046 XRenderFreeGlyphSet (dpy, font->glyphset);
1047 /* Free the glyphs */
1048 for (i = 0; i < font->num_glyphs; i++)
1049 {
1050 XftGlyph *xftg = font->glyphs[i];
1051 if (xftg)
1052 {
1053 if (xftg->bitmap)
1054 free (xftg->bitmap);
1055 free (xftg);
1056 }
1057 }
1058
1059 /* Free the pattern and the charset */
1060 FcPatternDestroy (font->public.pattern);
1061 FcCharSetDestroy (font->public.charset);
1062
1063 /* Finally, free the font structure */
1064 XftMemFree (XFT_MEM_FONT1, sizeof (XftFontInt) +
1065 font->num_glyphs * sizeof (XftGlyph *) +
1066 font->hash_value * sizeof (XftUcsHash));
1067 free (font);
1068}
1069
1070static XftFont *
1071XftFontFindNthUnref (XftDisplayInfo *info, int n)
1072{
1073 XftFont *public;
1074 XftFontInt *font;
1075
1076 for (public = info->fonts; public; public = font->next)
1077 {
1078 font = (XftFontInt*) public;
1079 if (!font->ref && !n--)
1080 break;
1081 }
1082 return public;
1083}
1084
1085_X_HIDDEN__attribute__((visibility("hidden"))) void
1086XftFontManageMemory (Display *dpy)
1087{
1088 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0);
1089 XftFont **prev;
1090 XftFont *public;
1091 XftFontInt *font;
1092
1093 if (!info)
1094 return;
1095 while (info->num_unref_fonts > info->max_unref_fonts)
1096 {
1097 public = XftFontFindNthUnref (info, rand() % info->num_unref_fonts);
1098 font = (XftFontInt *) public;
1099
1100 if (XftDebug () & XFT_DBG_CACHE128)
1101 printf ("freeing unreferenced font %s/%d size %dx%d\n",
1102 font->info.file->file, font->info.file->id,
1103 (int) font->info.xsize >> 6, (int) font->info.ysize >> 6);
1104
1105 /* Unhook from display list */
1106 for (prev = &info->fonts; *prev; prev = &(*(XftFontInt **) prev)->next)
1107 {
1108 if (*prev == public)
1109 {
1110 *prev = font->next;
1111 break;
1112 }
1113 }
1114 /* Unhook from hash list */
1115 for (prev = &info->fontHash[font->info.hash % XFT_NUM_FONT_HASH127];
1116 *prev;
1117 prev = &(*(XftFontInt **) prev)->hash_next)
1118 {
1119 if (*prev == public)
1120 {
1121 *prev = font->hash_next;
1122 break;
1123 }
1124 }
1125 /* Destroy the font */
1126 XftFontDestroy (dpy, public);
1127 --info->num_unref_fonts;
1128 }
1129}
1130
1131_X_EXPORT__attribute__((visibility("default"))) void
1132XftFontClose (Display *dpy, XftFont *public)
1133{
1134 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0);
1135 XftFontInt *font = (XftFontInt *) public;
1136
1137 if (--font->ref != 0)
1138 return;
1139
1140 if (info)
1141 {
1142 ++info->num_unref_fonts;
1143 XftFontManageMemory (dpy);
1144 }
1145 else
1146 {
1147 XftFontDestroy (dpy, public);
1148 }
1149}
1150
1151_X_EXPORT__attribute__((visibility("default"))) FcBool
1152XftInitFtLibrary (void)
1153{
1154 if (_XftFTlibrary)
1155 return FcTrue1;
1156 if (FT_Init_FreeType (&_XftFTlibrary))
1157 return FcFalse0;
1158 return FcTrue1;
1159}