]> git.pld-linux.org Git - packages/XFree86.git/blob - XFree86-Xft-update.patch
- outdated
[packages/XFree86.git] / XFree86-Xft-update.patch
1 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/Imakefile xc/lib/Xft/Imakefile
2 --- XFree86-4.0.2.orig/xc/lib/Xft/Imakefile     Sat Dec 16 12:33:01 2000
3 +++ XFree86-4.0.2/xc/lib/Xft/Imakefile  Fri Jan 19 20:25:58 2001
4 @@ -1,4 +1,4 @@
5 -XCOMM $XFree86: xc/lib/Xft/Imakefile,v 1.8 2000/12/15 17:12:52 keithp Exp $
6 +XCOMM $XFree86: xc/lib/Xft/Imakefile,v 1.9 2001/01/02 02:46:50 keithp Exp $
7  
8  #define DoNormalLib NormalLibXft
9  #define DoSharedLib SharedLibXft
10 @@ -33,8 +33,8 @@
11  
12  #ifdef Freetype2Dir
13  FT_HEADERS = XftFreetype.h
14 -   FT_SRCS = xftdir.c xftfreetype.c xftglyphs.c xftrender.c
15 -   FT_OBJS = xftdir.o xftfreetype.o xftglyphs.o xftrender.o
16 +   FT_SRCS = xftcache.c xftdir.c xftfreetype.c xftglyphs.c xftrender.c
17 +   FT_OBJS = xftcache.o xftdir.o xftfreetype.o xftglyphs.o xftrender.o
18  #endif
19  
20  HEADERS = Xft.h $(FT_HEADERS)
21 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/Xft.h xc/lib/Xft/Xft.h
22 --- XFree86-4.0.2.orig/xc/lib/Xft/Xft.h Fri Dec  8 02:51:26 2000
23 +++ XFree86-4.0.2/xc/lib/Xft/Xft.h      Fri Jan 19 20:25:58 2001
24 @@ -1,5 +1,5 @@
25  /*
26 - * $XFree86: xc/lib/Xft/Xft.h,v 1.13 2000/12/08 07:51:26 keithp Exp $
27 + * $XFree86: xc/lib/Xft/Xft.h,v 1.16 2001/01/02 02:46:50 keithp Exp $
28   *
29   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
30   *
31 @@ -57,6 +57,7 @@
32  /* defaults from resources */
33  #define XFT_SCALE          "scale"     /* double */
34  #define XFT_RENDER         "render"    /* Bool */
35 +#define XFT_MINSPACE       "minspace"  /* Bool use minimum line spacing */
36  
37  /* specific to FreeType rasterizer */
38  #define XFT_CHAR_WIDTH     "charwidth" /* Int */
39 @@ -254,6 +255,16 @@
40                  int            y,
41                  XftChar32      *string,
42                  int            len);
43 +
44 +void
45 +XftDrawStringUtf8 (XftDraw     *d,
46 +                  XftColor     *color,
47 +                  XftFont      *font,
48 +                  int          x, 
49 +                  int          y,
50 +                  XftChar8     *string,
51 +                  int          len);
52 +
53  void
54  XftDrawRect (XftDraw       *d,
55              XftColor       *color,
56 @@ -290,6 +301,13 @@
57                   int           len,
58                   XGlyphInfo    *extents);
59      
60 +void
61 +XftTextExtentsUtf8 (Display    *dpy,
62 +                   XftFont     *font,
63 +                   XftChar8    *string, 
64 +                   int         len,
65 +                   XGlyphInfo  *extents);
66 +
67  /* xftfont.c */
68  XftPattern *
69  XftFontMatch (Display *dpy, int screen, XftPattern *pattern, XftResult *result);
70 @@ -379,6 +397,9 @@
71  XftPattern *
72  XftNameParse (const char *name);
73  
74 +Bool
75 +XftNameUnparse (XftPattern *pat, char *dest, int len);
76 +
77  /* xftpat.c */
78  XftPattern *
79  XftPatternCreate (void);
80 @@ -442,12 +463,26 @@
81  
82  /* xftstr.c */
83  
84 +int
85 +XftUtf8ToUcs4 (XftChar8    *src_orig,
86 +              XftChar32   *dst,
87 +              int          len);
88 +
89 +Bool
90 +XftUtf8Len (XftChar8   *string,
91 +           int         len,
92 +           int         *nchar,
93 +           int         *wchar);
94 +
95  /* xftxlfd.c */
96  XftPattern *
97  XftXlfdParse (const char *xlfd_orig, Bool ignore_scalable, Bool complete);
98      
99  XFontStruct *
100  XftCoreOpen (Display *dpy, XftPattern *pattern);
101 +
102 +void
103 +XftCoreClose (Display *dpy, XFontStruct *font);
104  
105  _XFUNCPROTOEND
106  
107 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/XftFreetype.h xc/lib/Xft/XftFreetype.h
108 --- XFree86-4.0.2.orig/xc/lib/Xft/XftFreetype.h Sat Dec 16 12:33:01 2000
109 +++ XFree86-4.0.2/xc/lib/Xft/XftFreetype.h      Fri Jan 19 20:25:58 2001
110 @@ -1,5 +1,5 @@
111  /*
112 - * $XFree86: xc/lib/Xft/XftFreetype.h,v 1.7 2000/12/15 17:12:52 keithp Exp $
113 + * $XFree86: xc/lib/Xft/XftFreetype.h,v 1.12 2001/01/02 02:46:50 keithp Exp $
114   *
115   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
116   *
117 @@ -38,15 +38,15 @@
118      GlyphSet           glyphset;
119      int                        min_char;
120      int                        max_char;
121 -    int                        size;
122 +    FT_F26Dot6         size;
123      int                        ascent;
124      int                        descent;
125      int                        height;
126      int                        max_advance_width;
127 -    Bool               monospace;
128 +    int                        spacing;
129      int                        rgba;
130      Bool               antialias;
131 -    Bool               encoded;    /* use charmap */
132 +    int                        charmap;    /* -1 for unencoded */
133      XRenderPictFormat  *format;
134      XGlyphInfo         **realized;
135      int                        nrealized;
136 @@ -54,13 +54,32 @@
137  
138  _XFUNCPROTOBEGIN
139  
140 +/* xftdir.c */
141 +Bool
142 +XftDirScan (XftFontSet *set, const char *dir, Bool force);
143 +
144 +Bool
145 +XftDirSave (XftFontSet *set, const char *dir);
146 +
147  /* xftfreetype.c */
148 +XftPattern *
149 +XftFreeTypeQuery (const char *file, int id, int *count);
150 +
151 +Bool
152 +XftFreeTypeSetFace (FT_Face face, FT_F26Dot6 size, int charmap);
153 +
154  XftFontStruct *
155  XftFreeTypeOpen (Display *dpy, XftPattern *pattern);
156  
157  void
158  XftFreeTypeClose (Display *dpy, XftFontStruct *font);
159  
160 +XftFontStruct *
161 +XftFreeTypeGet (XftFont *font);
162 +
163 +Bool
164 +XftInitFtLibrary(void);
165 +
166  /* xftglyphs.c */
167  void
168  XftGlyphLoad (Display          *dpy,
169 @@ -104,6 +123,13 @@
170                    XftChar32 *string, int len);
171  
172  void
173 +XftRenderStringUtf8 (Display *dpy, Picture src, 
174 +                    XftFontStruct *font, Picture dst,
175 +                    int srcx, int srcy,
176 +                    int x, int y,
177 +                    XftChar8 *string, int len);
178 +
179 +void
180  XftRenderExtents8 (Display         *dpy,
181                    XftFontStruct    *font,
182                    XftChar8         *string, 
183 @@ -123,6 +149,13 @@
184                     XftChar32       *string, 
185                     int             len,
186                     XGlyphInfo      *extents);
187 +
188 +void
189 +XftRenderExtentsUtf8 (Display      *dpy,
190 +                     XftFontStruct *font,
191 +                     XftChar8      *string, 
192 +                     int           len,
193 +                     XGlyphInfo    *extents);
194  
195  XftFontStruct *
196  XftFreeTypeGet (XftFont *font);
197 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftcache.c xc/lib/Xft/xftcache.c
198 --- XFree86-4.0.2.orig/xc/lib/Xft/xftcache.c    Wed Dec 31 19:00:00 1969
199 +++ XFree86-4.0.2/xc/lib/Xft/xftcache.c Fri Jan 19 20:25:58 2001
200 @@ -0,0 +1,608 @@
201 +/*
202 + * $XFree86: xc/lib/Xft/xftcache.c,v 1.1 2001/01/02 02:46:51 keithp Exp $
203 + *
204 + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
205 + *
206 + * Permission to use, copy, modify, distribute, and sell this software and its
207 + * documentation for any purpose is hereby granted without fee, provided that
208 + * the above copyright notice appear in all copies and that both that
209 + * copyright notice and this permission notice appear in supporting
210 + * documentation, and that the name of Keith Packard not be used in
211 + * advertising or publicity pertaining to distribution of the software without
212 + * specific, written prior permission.  Keith Packard makes no
213 + * representations about the suitability of this software for any purpose.  It
214 + * is provided "as is" without express or implied warranty.
215 + *
216 + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
218 + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
219 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
220 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
221 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
222 + * PERFORMANCE OF THIS SOFTWARE.
223 + */
224 +
225 +#include <stdlib.h>
226 +#include <stdio.h>
227 +#include <unistd.h>
228 +#include <string.h>
229 +#include <ctype.h>
230 +#include <errno.h>
231 +#include <sys/types.h>
232 +#include <sys/stat.h>
233 +#include "xftint.h"
234 +
235 +typedef struct _XftFileCacheEnt {
236 +    struct _XftFileCacheEnt *next;
237 +    unsigned int           hash;
238 +    char                   *file;
239 +    int                            id;
240 +    time_t                 time;
241 +    char                   *name;
242 +    Bool                   referenced;
243 +} XftFileCacheEnt;
244 +
245 +#define HASH_SIZE   509
246 +
247 +typedef struct _XftFileCache {
248 +    XftFileCacheEnt    *ents[HASH_SIZE];
249 +    Bool               updated;
250 +    int                        entries;
251 +    int                        referenced;
252 +} XftFileCache;
253 +
254 +static XftFileCache    _XftFileCache;
255 +
256 +static unsigned int
257 +_XftFileCacheHash (char *string)
258 +{
259 +    unsigned int    h = 0;
260 +    char           c;
261 +
262 +    while ((c = *string++))
263 +       h = (h << 1) ^ c;
264 +    return h;
265 +}
266 +
267 +char *
268 +XftFileCacheFind (char *file, int id, int *count)
269 +{
270 +    XftFileCache    *cache;
271 +    unsigned int    hash;
272 +    char           *match;
273 +    XftFileCacheEnt *c, *name;
274 +    int                    maxid;
275 +    struct stat            statb;
276 +    
277 +    cache = &_XftFileCache;
278 +    match = file;
279 +    
280 +    hash = _XftFileCacheHash (match);
281 +    name = 0;
282 +    maxid = -1;
283 +    for (c = cache->ents[hash % HASH_SIZE]; c; c = c->next)
284 +    {
285 +       if (c->hash == hash && !strcmp (match, c->file))
286 +       {
287 +           if (c->id > maxid)
288 +               maxid = c->id;
289 +           if (c->id == id)
290 +           {
291 +               if (stat (file, &statb) < 0)
292 +               {
293 +                   if (_XftFontDebug () & XFT_DBG_CACHE)
294 +                       printf (" file missing\n");
295 +                   return 0;
296 +               }
297 +               if (statb.st_mtime != c->time)
298 +               {
299 +                   if (_XftFontDebug () & XFT_DBG_CACHE)
300 +                       printf (" timestamp mismatch (was %d is %d)\n",
301 +                               (int) c->time, (int) statb.st_mtime);
302 +                   return 0;
303 +               }
304 +               if (!c->referenced)
305 +               {
306 +                   cache->referenced++;
307 +                   c->referenced = True;
308 +               }
309 +               name = c;
310 +           }
311 +       }
312 +    }
313 +    if (!name)
314 +       return 0;
315 +    *count = maxid;
316 +    return name->name;
317 +}
318 +
319 +/*
320 + * Cache file syntax is quite simple:
321 + *
322 + * "file_name" id time "font_name" \n
323 + */
324
325 +static Bool
326 +_XftFileCacheReadString (FILE *f, char *dest, int len)
327 +{
328 +    int            c;
329 +    Bool    escape;
330 +
331 +    while ((c = getc (f)) != EOF)
332 +       if (c == '"')
333 +           break;
334 +    if (c == EOF)
335 +       return False;
336 +    if (len == 0)
337 +       return False;
338 +    
339 +    escape = False;
340 +    while ((c = getc (f)) != EOF)
341 +    {
342 +       if (!escape)
343 +       {
344 +           switch (c) {
345 +           case '"':
346 +               *dest++ = '\0';
347 +               return True;
348 +           case '\\':
349 +               escape = True;
350 +               continue;
351 +           }
352 +       }
353 +        if (--len <= 1)
354 +           return False;
355 +       *dest++ = c;
356 +       escape = False;
357 +    }
358 +    return False;
359 +}
360 +
361 +static Bool
362 +_XftFileCacheReadUlong (FILE *f, unsigned long *dest)
363 +{
364 +    unsigned long   t;
365 +    int                    c;
366 +
367 +    while ((c = getc (f)) != EOF)
368 +    {
369 +       if (!isspace (c))
370 +           break;
371 +    }
372 +    if (c == EOF)
373 +       return False;
374 +    t = 0;
375 +    for (;;)
376 +    {
377 +       if (c == EOF || isspace (c))
378 +           break;
379 +       if (!isdigit (c))
380 +           return False;
381 +       t = t * 10 + (c - '0');
382 +       c = getc (f);
383 +    }
384 +    *dest = t;
385 +    return True;
386 +}
387 +
388 +static Bool
389 +_XftFileCacheReadInt (FILE *f, int *dest)
390 +{
391 +    unsigned long   t;
392 +    Bool           ret;
393 +
394 +    ret = _XftFileCacheReadUlong (f, &t);
395 +    if (ret)
396 +       *dest = (int) t;
397 +    return ret;
398 +}
399 +
400 +static Bool
401 +_XftFileCacheReadTime (FILE *f, time_t *dest)
402 +{
403 +    unsigned long   t;
404 +    Bool           ret;
405 +
406 +    ret = _XftFileCacheReadUlong (f, &t);
407 +    if (ret)
408 +       *dest = (time_t) t;
409 +    return ret;
410 +}
411 +
412 +static Bool
413 +_XftFileCacheAdd (XftFileCache *cache,
414 +                 char          *file,
415 +                 int           id,
416 +                 time_t        time,
417 +                 char          *name,
418 +                 Bool          replace)
419 +{
420 +    XftFileCacheEnt    *c;
421 +    XftFileCacheEnt    **prev, *old;
422 +    unsigned int    hash;
423 +
424 +    if (_XftFontDebug () & XFT_DBG_CACHE)
425 +    {
426 +       printf ("%s face %s/%d as %s\n", replace ? "Replace" : "Add",
427 +               file, id, name);
428 +    }
429 +    hash = _XftFileCacheHash (file);
430 +    for (prev = &cache->ents[hash % HASH_SIZE]; 
431 +        (old = *prev);
432 +        prev = &(*prev)->next)
433 +    {
434 +       if (old->hash == hash && old->id == id && !strcmp (old->file, file))
435 +           break;
436 +    }
437 +    if (*prev)
438 +    {
439 +       if (!replace)
440 +           return False;
441 +
442 +       old = *prev;
443 +       if (old->referenced)
444 +           cache->referenced--;
445 +       *prev = old->next;
446 +       free (old);
447 +       cache->entries--;
448 +    }
449 +       
450 +    c = malloc (sizeof (XftFileCacheEnt) +
451 +               strlen (file) + 1 +
452 +               strlen (name) + 1);
453 +    if (!c)
454 +       return False;
455 +    c->next = *prev;
456 +    *prev = c;
457 +    c->hash = hash;
458 +    c->file = (char *) (c + 1);
459 +    c->id = id;
460 +    c->name = c->file + strlen (file) + 1;
461 +    strcpy (c->file, file);
462 +    c->time = time;
463 +    c->referenced = replace;
464 +    strcpy (c->name, name);
465 +    cache->entries++;
466 +    return True;
467 +}
468 +
469 +void
470 +XftFileCacheDispose (void)
471 +{
472 +    XftFileCache    *cache;
473 +    XftFileCacheEnt *c, *next;
474 +    int                    h;
475 +
476 +    cache = &_XftFileCache;
477 +    
478 +    for (h = 0; h < HASH_SIZE; h++)
479 +    {
480 +       for (c = cache->ents[h]; c; c = next)
481 +       {
482 +           next = c->next;
483 +           free (c);
484 +       }
485 +       cache->ents[h] = 0;
486 +    }
487 +    cache->entries = 0;
488 +    cache->referenced = 0;
489 +    cache->updated = False;
490 +}
491 +
492 +void
493 +XftFileCacheLoad (char *cache_file)
494 +{
495 +    XftFileCache    *cache;
496 +    FILE           *f;
497 +    char           file[8192];
498 +    int                    id;
499 +    time_t         time;
500 +    char           name[8192];
501 +
502 +    f = fopen (cache_file, "r");
503 +    if (!f)
504 +       return;
505 +
506 +    cache = &_XftFileCache;
507 +
508 +    cache->updated = False;
509 +    while (_XftFileCacheReadString (f, file, sizeof (file)) &&
510 +          _XftFileCacheReadInt (f, &id) &&
511 +          _XftFileCacheReadTime (f, &time) &&
512 +          _XftFileCacheReadString (f, name, sizeof (name)))
513 +    {
514 +       (void) _XftFileCacheAdd (cache, file, id, time, name, False);
515 +    }
516 +    fclose (f);
517 +}
518 +
519 +Bool
520 +XftFileCacheUpdate (char *file, int id, char *name)
521 +{
522 +    XftFileCache    *cache;
523 +    char           *match;
524 +    struct stat            statb;
525 +    Bool           ret;
526 +
527 +    cache = &_XftFileCache;
528 +    match = file;
529 +
530 +    if (stat (file, &statb) < 0)
531 +       return False;
532 +    ret = _XftFileCacheAdd (cache, match, id, 
533 +                           statb.st_mtime, name, True);
534 +    if (ret)
535 +       cache->updated = True;
536 +    return ret;
537 +}
538 +
539 +static Bool
540 +_XftFileCacheWriteString (FILE *f, char *string)
541 +{
542 +    char    c;
543 +
544 +    if (putc ('"', f) == EOF)
545 +       return False;
546 +    while ((c = *string++))
547 +    {
548 +       switch (c) {
549 +       case '"':
550 +       case '\\':
551 +           if (putc ('\\', f) == EOF)
552 +               return False;
553 +           /* fall through */
554 +       default:
555 +           if (putc (c, f) == EOF)
556 +               return False;
557 +       }
558 +    }
559 +    if (putc ('"', f) == EOF)
560 +       return False;
561 +    return True;
562 +}
563 +
564 +static Bool
565 +_XftFileCacheWriteUlong (FILE *f, unsigned long t)
566 +{
567 +    int            pow;
568 +    unsigned long   temp, digit;
569 +
570 +    temp = t;
571 +    pow = 1;
572 +    while (temp >= 10)
573 +    {
574 +       temp /= 10;
575 +       pow *= 10;
576 +    }
577 +    temp = t;
578 +    while (pow)
579 +    {
580 +       digit = temp / pow;
581 +       if (putc ((char) digit + '0', f) == EOF)
582 +           return False;
583 +       temp = temp - pow * digit;
584 +       pow = pow / 10;
585 +    }
586 +    return True;
587 +}
588 +
589 +static Bool
590 +_XftFileCacheWriteInt (FILE *f, int i)
591 +{
592 +    return _XftFileCacheWriteUlong (f, (unsigned long) i);
593 +}
594 +
595 +static Bool
596 +_XftFileCacheWriteTime (FILE *f, time_t t)
597 +{
598 +    return _XftFileCacheWriteUlong (f, (unsigned long) t);
599 +}
600 +
601 +Bool
602 +XftFileCacheSave (char *cache_file)
603 +{
604 +    XftFileCache    *cache;
605 +    char           *lck;
606 +    char           *tmp;
607 +    FILE           *f;
608 +    int                    h;
609 +    XftFileCacheEnt *c;
610 +
611 +    cache = &_XftFileCache;
612 +
613 +    if (!cache->updated && cache->referenced == cache->entries)
614 +       return True;
615 +    
616 +    lck = malloc (strlen (cache_file)*2 + 4);
617 +    if (!lck)
618 +       goto bail0;
619 +    tmp = lck + strlen (cache_file) + 2;
620 +    strcpy (lck, cache_file);
621 +    strcat (lck, "L");
622 +    strcpy (tmp, cache_file);
623 +    strcat (tmp, "T");
624 +    if (link (lck, cache_file) < 0 && errno != ENOENT)
625 +       goto bail1;
626 +    if (access (tmp, F_OK) == 0)
627 +       goto bail2;
628 +    f = fopen (tmp, "w");
629 +    if (!f)
630 +       goto bail2;
631 +
632 +    for (h = 0; h < HASH_SIZE; h++)
633 +    {
634 +       for (c = cache->ents[h]; c; c = c->next)
635 +       {
636 +           if (!c->referenced)
637 +               continue;
638 +           if (!_XftFileCacheWriteString (f, c->file))
639 +               goto bail4;
640 +           if (putc (' ', f) == EOF)
641 +               goto bail4;
642 +           if (!_XftFileCacheWriteInt (f, c->id))
643 +               goto bail4;
644 +           if (putc (' ', f) == EOF)
645 +               goto bail4;
646 +           if (!_XftFileCacheWriteTime (f, c->time))
647 +               goto bail4;
648 +           if (putc (' ', f) == EOF)
649 +               goto bail4;
650 +           if (!_XftFileCacheWriteString (f, c->name))
651 +               goto bail4;
652 +           if (putc ('\n', f) == EOF)
653 +               goto bail4;
654 +       }
655 +    }
656 +
657 +    if (fclose (f) == EOF)
658 +       goto bail3;
659 +    
660 +    if (rename (tmp, cache_file) < 0)
661 +       goto bail3;
662 +    
663 +    unlink (lck);
664 +    cache->updated = False;
665 +    return True;
666 +
667 +bail4:
668 +    fclose (f);
669 +bail3:
670 +    unlink (tmp);
671 +bail2:
672 +    unlink (lck);
673 +bail1:
674 +    free (lck);
675 +bail0:
676 +    return False;
677 +}
678 +
679 +Bool
680 +XftFileCacheReadDir (XftFontSet *set, const char *cache_file)
681 +{
682 +    XftPattern     *font;
683 +    FILE           *f;
684 +    char           *path;
685 +    char           *base;
686 +    char           file[8192];
687 +    int                    id;
688 +    char           name[8192];
689 +    Bool           ret = False;
690 +
691 +    if (_XftFontDebug () & XFT_DBG_CACHE)
692 +    {
693 +       printf ("XftFileCacheReadDir cache_file \"%s\"\n", cache_file);
694 +    }
695 +    
696 +    f = fopen (cache_file, "r");
697 +    if (!f)
698 +    {
699 +       if (_XftFontDebug () & XFT_DBG_CACHE)
700 +       {
701 +           printf (" no cache file\n");
702 +       }
703 +       goto bail0;
704 +    }
705 +
706 +    base = strrchr (cache_file, '/');
707 +    if (!base)
708 +       goto bail1;
709 +    base++;
710 +    path = malloc (base - cache_file + 8192 + 1);
711 +    if (!path)
712 +       goto bail1;
713 +    memcpy (path, cache_file, base - cache_file);
714 +    base = path + (base - cache_file);
715 +    
716 +    while (_XftFileCacheReadString (f, file, sizeof (file)) &&
717 +          _XftFileCacheReadInt (f, &id) &&
718 +          _XftFileCacheReadString (f, name, sizeof (name)))
719 +    {
720 +       font = XftNameParse (name);
721 +       if (font)
722 +       {
723 +           strcpy (base, file);
724 +           if (_XftFontDebug () & XFT_DBG_CACHEV)
725 +           {
726 +               printf (" dir cache file \"%s\"\n", file);
727 +           }
728 +           XftPatternAddString (font, XFT_FILE, path);
729 +           if (!XftFontSetAdd (set, font))
730 +               goto bail2;
731 +       }
732 +    }
733 +    if (_XftFontDebug () & XFT_DBG_CACHE)
734 +    {
735 +       printf (" cache loaded\n");
736 +    }
737 +    
738 +    ret = True;
739 +bail2:
740 +    free (path);
741 +bail1:
742 +    fclose (f);
743 +bail0:
744 +    return ret;
745 +}
746 +
747 +Bool
748 +XftFileCacheWriteDir (XftFontSet *set, const char *cache_file)
749 +{
750 +    XftPattern     *font;
751 +    FILE           *f;
752 +    char           name[8192];
753 +    char           *file, *base;
754 +    int                    n;
755 +    int                    id;
756 +
757 +    if (_XftFontDebug () & XFT_DBG_CACHE)
758 +       printf ("XftFileCacheWriteDir cache_file \"%s\"\n", cache_file);
759 +    
760 +    f = fopen (cache_file, "w");
761 +    if (!f)
762 +    {
763 +       if (_XftFontDebug () & XFT_DBG_CACHE)
764 +           printf (" can't create \"%s\"\n", cache_file);
765 +       goto bail0;
766 +    }
767 +    for (n = 0; n < set->nfont; n++)
768 +    {
769 +       font = set->fonts[n];
770 +       if (XftPatternGetString (font, XFT_FILE, 0, &file) != XftResultMatch)
771 +           goto bail1;
772 +       base = strrchr (file, '/');
773 +       if (base)
774 +           base = base + 1;
775 +       else
776 +           base = file;
777 +       if (XftPatternGetInteger (font, XFT_INDEX, 0, &id) != XftResultMatch)
778 +           goto bail1;
779 +       if (!XftNameUnparse (font, name, sizeof (name)))
780 +           goto bail1;
781 +       if (_XftFontDebug () & XFT_DBG_CACHEV)
782 +           printf (" write file \"%s\"\n", base);
783 +       if (!_XftFileCacheWriteString (f, base))
784 +           goto bail1;
785 +       if (putc (' ', f) == EOF)
786 +           goto bail1;
787 +       if (!_XftFileCacheWriteInt (f, id))
788 +           goto bail1;
789 +        if (putc (' ', f) == EOF)
790 +           goto bail1;
791 +       if (!_XftFileCacheWriteString (f, name))
792 +           goto bail1;
793 +       if (putc ('\n', f) == EOF)
794 +           goto bail1;
795 +    }
796 +    if (fclose (f) == EOF)
797 +       goto bail0;
798 +    
799 +    if (_XftFontDebug () & XFT_DBG_CACHE)
800 +       printf (" cache written\n");
801 +    return True;
802 +    
803 +bail1:
804 +    fclose (f);
805 +bail0:
806 +    unlink (cache_file);
807 +    return False;
808 +}
809 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftcfg.c xc/lib/Xft/xftcfg.c
810 --- XFree86-4.0.2.orig/xc/lib/Xft/xftcfg.c      Tue Dec 19 08:12:29 2000
811 +++ XFree86-4.0.2/xc/lib/Xft/xftcfg.c   Fri Jan 19 20:25:58 2001
812 @@ -1,5 +1,5 @@
813  /*
814 - * $XFree86: xc/lib/Xft/xftcfg.c,v 1.7 2000/12/17 09:11:37 keithp Exp $
815 + * $XFree86: xc/lib/Xft/xftcfg.c,v 1.8 2001/01/02 02:46:51 keithp Exp $
816   *
817   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
818   *
819 @@ -35,6 +35,9 @@
820  char           **XftConfigDirs = XftConfigDefaultDirs;
821  static int     XftConfigNdirs;
822  
823 +char           XftConfigDefaultCache[] = "~/.xftcache";
824 +char           *XftConfigCache = 0;
825 +
826  static XftSubst        *XftSubsts;
827  /* #define XFT_DEBUG_EDIT */
828  
829 @@ -51,6 +54,8 @@
830         if (!h)
831             return False;
832         dir = (char *) malloc (strlen (h) + strlen (d));
833 +       if (!dir)
834 +           return False;
835         strcpy (dir, h);
836         strcat (dir, d+1);
837      }
838 @@ -78,6 +83,41 @@
839         free (XftConfigDirs);
840      XftConfigDirs = dirs;
841      return True;
842 +}
843 +
844 +Bool
845 +XftConfigSetCache (char *c)
846 +{
847 +    char    *new;
848 +    char    *h;
849 +
850 +    if (*c == '~')
851 +    {
852 +       h = getenv ("HOME");
853 +       if (!h)
854 +           return False;
855 +       new = (char *) malloc (strlen (h) + strlen (c));
856 +       if (!new)
857 +           return False;
858 +       strcpy (new, h);
859 +       strcat (new, c+1);
860 +    }
861 +    else
862 +    {
863 +       new = _XftSaveString (c);
864 +    }
865 +    if (XftConfigCache)
866 +       free (XftConfigCache);
867 +    XftConfigCache = new;
868 +    return True;
869 +}
870 +
871 +char *
872 +XftConfigGetCache (void)
873 +{
874 +    if (!XftConfigCache)
875 +       XftConfigSetCache (XftConfigDefaultCache);
876 +    return XftConfigCache;
877  }
878  
879  static int XftSubstsMaxObjects;
880 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftcore.c xc/lib/Xft/xftcore.c
881 --- XFree86-4.0.2.orig/xc/lib/Xft/xftcore.c     Fri Dec  8 02:51:27 2000
882 +++ XFree86-4.0.2/xc/lib/Xft/xftcore.c  Fri Jan 19 20:25:58 2001
883 @@ -1,5 +1,5 @@
884  /*
885 - * $XFree86: xc/lib/Xft/xftcore.c,v 1.4 2000/12/08 07:51:27 keithp Exp $
886 + * $XFree86: xc/lib/Xft/xftcore.c,v 1.5 2000/12/20 00:28:44 keithp Exp $
887   *
888   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
889   *
890 @@ -65,6 +65,37 @@
891      return xc;
892  }
893  
894 +XChar2b *
895 +XftCoreConvertUtf8 (XftChar8   *string,
896 +                   int         len,
897 +                   XChar2b     xcloc[XFT_CORE_N16LOCAL],
898 +                   int         *nchar)
899 +{
900 +    XChar2b    *xc;
901 +    XftChar32  c;
902 +    int                i;
903 +    int                n, width;
904 +    int                clen;
905 +    
906 +    if (!XftUtf8Len (string, len, &n, &width))
907 +       return 0;
908 +    
909 +    if (n < XFT_CORE_N16LOCAL)
910 +       xc = xcloc;
911 +    else
912 +       xc = (XChar2b *) malloc (n * sizeof (XChar2b));
913 +    for (i = 0; i < n; i++)
914 +    {
915 +       clen = XftUtf8ToUcs4 (string, &c, len);
916 +       xc[i].byte1 = c & 0xff;
917 +       xc[i].byte2 = (c >> 8) & 0xff;
918 +       string += clen;
919 +       len -= clen;
920 +    }
921 +    *nchar = n;
922 +    return xc;
923 +}
924 +
925  void
926  XftCoreExtents8 (Display       *dpy,
927                  XFontStruct    *fs,
928 @@ -109,6 +140,8 @@
929      xc = XftCoreConvert16 (string, len, xcloc);
930      XTextExtents16 (fs, xc, len, &direction,
931                     &ascent, &descent, &overall);
932 +    if (xc != xcloc)
933 +       free (xc);
934      if (overall.lbearing < overall.rbearing)
935      {
936         extents->x = overall.lbearing;
937 @@ -140,6 +173,42 @@
938      xc = XftCoreConvert32 (string, len, xcloc);
939      XTextExtents16 (fs, xc, len, &direction,
940                     &ascent, &descent, &overall);
941 +    if (xc != xcloc)
942 +       free (xc);
943 +    if (overall.lbearing < overall.rbearing)
944 +    {
945 +       extents->x = overall.lbearing;
946 +       extents->width = overall.rbearing - overall.lbearing;
947 +    }
948 +    else
949 +    {
950 +       extents->x = overall.rbearing;
951 +       extents->width = overall.lbearing - overall.rbearing;
952 +    }
953 +    extents->y = -overall.ascent;
954 +    extents->height = overall.ascent + overall.descent;
955 +    extents->xOff = overall.width;
956 +    extents->yOff = 0;
957 +}
958 +
959 +void
960 +XftCoreExtentsUtf8 (Display        *dpy,
961 +                   XFontStruct     *fs,
962 +                   XftChar8        *string, 
963 +                   int             len,
964 +                   XGlyphInfo      *extents)
965 +{
966 +    int                direction;
967 +    int                ascent, descent;
968 +    XCharStruct overall;
969 +    XChar2b    *xc, xcloc[XFT_CORE_N16LOCAL];
970 +    int                n;
971 +
972 +    xc = XftCoreConvertUtf8 (string, len, xcloc, &n);
973 +    XTextExtents16 (fs, xc, n, &direction,
974 +                   &ascent, &descent, &overall);
975 +    if (xc != xcloc)
976 +       free (xc);
977      if (overall.lbearing < overall.rbearing)
978      {
979         extents->x = overall.lbearing;
980 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftdir.c xc/lib/Xft/xftdir.c
981 --- XFree86-4.0.2.orig/xc/lib/Xft/xftdir.c      Wed Nov 29 03:39:21 2000
982 +++ XFree86-4.0.2/xc/lib/Xft/xftdir.c   Fri Jan 19 20:25:58 2001
983 @@ -1,5 +1,5 @@
984  /*
985 - * $XFree86: xc/lib/Xft/xftdir.c,v 1.1 2000/11/29 08:39:21 keithp Exp $
986 + * $XFree86: xc/lib/Xft/xftdir.c,v 1.2 2001/01/02 02:46:51 keithp Exp $
987   *
988   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
989   *
990 @@ -29,38 +29,73 @@
991  #include "xftint.h"
992  
993  Bool
994 -XftDirScan (XftFontSet *set, const char *dir)
995 +XftDirScan (XftFontSet *set, const char *dir, Bool force)
996  {
997      DIR                    *d;
998      struct dirent   *e;
999      char           *file;
1000      char           *base;
1001      XftPattern     *font;
1002 +    char           *name;
1003      int                    count;
1004      Bool           ret = True;
1005      int                    id;
1006  
1007 -    d = opendir (dir);
1008 -    if (!d)
1009 -       return False;
1010      file = (char *) malloc (strlen (dir) + 1 + 256 + 1);
1011      if (!file)
1012 -    {
1013 -       closedir (d);
1014         return False;
1015 -    }
1016 +
1017      strcpy (file, dir);
1018      strcat (file, "/");
1019      base = file + strlen (file);
1020 +    if (!force)
1021 +    {
1022 +       strcpy (base, "XftCache");
1023 +       
1024 +       if (XftFileCacheReadDir (set, file))
1025 +       {
1026 +           free (file);
1027 +           return True;
1028 +       }
1029 +    }
1030 +    
1031 +    d = opendir (dir);
1032 +    if (!d)
1033 +    {
1034 +       free (file);
1035 +       return False;
1036 +    }
1037      while (ret && (e = readdir (d)))
1038      {
1039         if (e->d_name[0] != '.')
1040         {
1041 -           strcpy (base, e->d_name);
1042             id = 0;
1043 +           strcpy (base, e->d_name);
1044             do
1045             {
1046 -               font = XftFreeTypeQuery (file, id, &count);
1047 +               if (!force)
1048 +                   name = XftFileCacheFind (file, id, &count);
1049 +               else
1050 +                   name = 0;
1051 +               if (name)
1052 +               {
1053 +                   font = XftNameParse (name);
1054 +                   if (font)
1055 +                       XftPatternAddString (font, XFT_FILE, file);
1056 +               }
1057 +               else
1058 +               {
1059 +                   font = XftFreeTypeQuery (file, id, &count);
1060 +                   if (font && !force)
1061 +                   {
1062 +                       char    unparse[8192];
1063 +
1064 +                       if (XftNameUnparse (font, unparse, sizeof (unparse)))
1065 +                       {
1066 +                           (void) XftFileCacheUpdate (file, id, unparse);
1067 +                       }
1068 +                   }
1069 +               }
1070                 if (font)
1071                 {
1072                     if (!XftFontSetAdd (set, font))
1073 @@ -75,4 +110,23 @@
1074      return ret;
1075  }
1076  
1077 -           
1078 +Bool
1079 +XftDirSave (XftFontSet *set, const char *dir)
1080 +{
1081 +    char           *file;
1082 +    char           *base;
1083 +    Bool           ret;
1084 +    
1085 +    file = (char *) malloc (strlen (dir) + 1 + 256 + 1);
1086 +    if (!file)
1087 +       return False;
1088 +
1089 +    strcpy (file, dir);
1090 +    strcat (file, "/");
1091 +    base = file + strlen (file);
1092 +    strcpy (base, "XftCache");
1093 +    ret = XftFileCacheWriteDir (set, file);
1094 +    free (file);
1095 +    return ret;
1096 +}
1097 +
1098 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftdpy.c xc/lib/Xft/xftdpy.c
1099 --- XFree86-4.0.2.orig/xc/lib/Xft/xftdpy.c      Tue Dec 19 08:12:29 2000
1100 +++ XFree86-4.0.2/xc/lib/Xft/xftdpy.c   Fri Jan 19 20:25:58 2001
1101 @@ -1,5 +1,5 @@
1102  /*
1103 - * $XFree86: xc/lib/Xft/xftdpy.c,v 1.4 2000/12/17 08:30:45 keithp Exp $
1104 + * $XFree86: xc/lib/Xft/xftdpy.c,v 1.5 2000/12/20 00:20:48 keithp Exp $
1105   *
1106   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
1107   *
1108 @@ -22,6 +22,7 @@
1109   * PERFORMANCE OF THIS SOFTWARE.
1110   */
1111  
1112 +#include <stdio.h>
1113  #include <stdlib.h>
1114  #include <ctype.h>
1115  #include <X11/Xlibint.h>
1116 @@ -81,6 +82,34 @@
1117      info->defaults = 0;
1118      info->coreFonts = 0;
1119      info->hasRender = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0;
1120 +    if (_XftFontDebug () & XFT_DBG_RENDER)
1121 +    {
1122 +       Visual              *visual = DefaultVisual (dpy, DefaultScreen (dpy));
1123 +       XRenderPictFormat   *format = XRenderFindVisualFormat (dpy, visual);
1124 +       
1125 +       printf ("XftDisplayInfoGet Default visual 0x%x ", 
1126 +               (int) visual->visualid);
1127 +       if (format)
1128 +       {
1129 +           if (format->type == PictTypeDirect)
1130 +           {
1131 +               printf ("format %d,%d,%d,%d\n",
1132 +                       format->direct.alpha,
1133 +                       format->direct.red,
1134 +                       format->direct.green,
1135 +                       format->direct.blue);
1136 +           }
1137 +           else
1138 +           {
1139 +               printf ("format indexed\n");
1140 +           }
1141 +       }
1142 +       else
1143 +           printf ("No Render format for default visual\n");
1144 +       
1145 +       printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n",
1146 +               info->hasRender ? "True" : "False");
1147 +    }
1148      
1149      info->next = _XftDisplayInfo;
1150      _XftDisplayInfo = info;
1151 @@ -89,6 +118,10 @@
1152  bail1:
1153      free (info);
1154  bail0:
1155 +    if (_XftFontDebug () & XFT_DBG_RENDER)
1156 +    {
1157 +       printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n");
1158 +    }
1159      return 0;
1160  }
1161  
1162 @@ -209,6 +242,8 @@
1163         goto bail1;
1164      if (!_XftDefaultInitBool (dpy, pat, XFT_ANTIALIAS))
1165         goto bail1;
1166 +    if (!_XftDefaultInitBool (dpy, pat, XFT_MINSPACE))
1167 +       goto bail1;
1168      
1169      return pat;
1170      
1171 @@ -343,6 +378,12 @@
1172         XftPatternAddInteger (pattern, XFT_RGBA,
1173                               XftDefaultGetInteger (dpy, XFT_RGBA, screen, 
1174                                                     XFT_RGBA_NONE));
1175 +    }
1176 +    if (XftPatternGet (pattern, XFT_MINSPACE, 0, &v) == XftResultNoMatch)
1177 +    {
1178 +       XftPatternAddBool (pattern, XFT_MINSPACE,
1179 +                          XftDefaultGetBool (dpy, XFT_MINSPACE, screen,
1180 +                                             False));
1181      }
1182      if (XftPatternGet (pattern, XFT_PIXEL_SIZE, 0, &v) == XftResultNoMatch)
1183      {
1184 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftdraw.c xc/lib/Xft/xftdraw.c
1185 --- XFree86-4.0.2.orig/xc/lib/Xft/xftdraw.c     Sat Dec 16 12:33:01 2000
1186 +++ XFree86-4.0.2/xc/lib/Xft/xftdraw.c  Fri Jan 19 20:25:58 2001
1187 @@ -1,5 +1,5 @@
1188  /*
1189 - * $XFree86: xc/lib/Xft/xftdraw.c,v 1.10 2000/12/15 17:12:52 keithp Exp $
1190 + * $XFree86: xc/lib/Xft/xftdraw.c,v 1.12 2000/12/20 00:28:44 keithp Exp $
1191   *
1192   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
1193   *
1194 @@ -22,6 +22,7 @@
1195   * PERFORMANCE OF THIS SOFTWARE.
1196   */
1197  
1198 +#include <stdio.h>
1199  #include <stdlib.h>
1200  #include "xftint.h"
1201  #include <X11/Xutil.h>
1202 @@ -200,6 +201,14 @@
1203         return False;
1204      if (memcmp (&color->color, &draw->render.fg_color, sizeof (XRenderColor)))
1205      {
1206 +       if (_XftFontDebug () & XFT_DBG_DRAW)
1207 +       {
1208 +           printf ("Switching to color %04x,%04x,%04x,%04x\n",
1209 +                   color->color.alpha,
1210 +                   color->color.red,
1211 +                   color->color.green,
1212 +                   color->color.blue);
1213 +       }
1214         XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.fg_pict,
1215                               &color->color, 0, 0, 1, 1);
1216         draw->render.fg_color = color->color;
1217 @@ -255,6 +264,10 @@
1218                 XftChar8        *string,
1219                 int             len)
1220  {
1221 +    if (_XftFontDebug () & XFT_DBG_DRAW)
1222 +    {
1223 +       printf ("DrawString \"%*.*s\"\n", len, len, string);
1224 +    }
1225      if (font->core)
1226      {
1227         XftDrawCorePrepare (draw, color, font);
1228 @@ -331,6 +344,41 @@
1229      }
1230  #endif
1231  }
1232 +
1233 +void
1234 +XftDrawStringUtf8 (XftDraw     *draw,
1235 +                  XftColor     *color,
1236 +                  XftFont      *font,
1237 +                  int          x,
1238 +                  int          y,
1239 +                  XftChar8     *string,
1240 +                  int          len)
1241 +{
1242 +    if (font->core)
1243 +    {
1244 +       XChar2b     *xc;
1245 +       XChar2b     xcloc[XFT_CORE_N16LOCAL];
1246 +       int         n;
1247 +       
1248 +       XftDrawCorePrepare (draw, color, font);
1249 +       xc = XftCoreConvertUtf8 (string, len, xcloc, &n);
1250 +       if (xc)
1251 +       {
1252 +           XDrawString16 (draw->dpy, draw->drawable, draw->core.draw_gc, x, y, 
1253 +                          xc, n);
1254 +       }
1255 +       if (xc != xcloc)
1256 +           free (xc);
1257 +    }
1258 +#ifdef FREETYPE2
1259 +    else if (XftDrawRenderPrepare (draw, color, font))
1260 +    {
1261 +       XftRenderStringUtf8 (draw->dpy, draw->render.fg_pict, font->u.ft.font,
1262 +                            draw->render.pict, 0, 0, x, y, string, len);
1263 +    }
1264 +#endif
1265 +}
1266 +
1267  
1268  void
1269  XftDrawRect (XftDraw       *draw,
1270 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftextent.c xc/lib/Xft/xftextent.c
1271 --- XFree86-4.0.2.orig/xc/lib/Xft/xftextent.c   Sat Dec 16 12:33:01 2000
1272 +++ XFree86-4.0.2/xc/lib/Xft/xftextent.c        Fri Jan 19 20:25:58 2001
1273 @@ -1,5 +1,5 @@
1274  /*
1275 - * $XFree86: xc/lib/Xft/xftextent.c,v 1.4 2000/12/15 17:12:52 keithp Exp $
1276 + * $XFree86: xc/lib/Xft/xftextent.c,v 1.5 2000/12/20 00:28:44 keithp Exp $
1277   *
1278   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
1279   *
1280 @@ -22,6 +22,7 @@
1281   * PERFORMANCE OF THIS SOFTWARE.
1282   */
1283  
1284 +#include <stdlib.h>
1285  #include "xftint.h"
1286  
1287  void
1288 @@ -79,4 +80,110 @@
1289         XftRenderExtents32 (dpy, font->u.ft.font, string, len, extents);
1290      }
1291  #endif
1292 +}
1293 +
1294 +void
1295 +XftTextExtentsUtf8 (Display    *dpy,
1296 +                   XftFont     *font,
1297 +                   XftChar8    *string, 
1298 +                   int         len,
1299 +                   XGlyphInfo  *extents)
1300 +{
1301 +    XftChar8   *src;
1302 +    XftChar32  c;
1303 +    XftChar32  lbuf[4096];
1304 +    XftChar32  *dst;
1305 +    XftChar8   *dst8;
1306 +    XftChar16  *dst16;
1307 +    XftChar32  *dst32;
1308 +    int                rlen, clen;
1309 +    int                width = 1;
1310 +    int                n;
1311 +
1312 +    /* compute needed width */
1313 +    src = string;
1314 +    rlen = len;
1315 +    n = 0;
1316 +    while (rlen)
1317 +    {
1318 +       clen = XftUtf8ToUcs4 (src, &c, rlen);
1319 +       if (clen <= 0)  /* malformed UTF8 string */
1320 +       {
1321 +           memset (extents, 0, sizeof (XGlyphInfo));
1322 +           return;
1323 +       }
1324 +       if (c >= 0x10000)
1325 +           width = 4;
1326 +       else if (c >= 0x100)
1327 +       {
1328 +           if (width == 1)
1329 +               width = 2;
1330 +       }
1331 +       src += clen;
1332 +       rlen -= clen;
1333 +       n++;
1334 +    }
1335 +    dst = lbuf;
1336 +    if (n * width > sizeof (lbuf))
1337 +    {
1338 +       dst = (XftChar32 *) malloc (n * width);
1339 +       if (!dst)
1340 +       {
1341 +           memset (extents, 0, sizeof (XGlyphInfo));
1342 +           return;
1343 +       }
1344 +    }
1345 +    
1346 +    switch (width) {
1347 +    case 4:
1348 +       src = string;
1349 +       rlen = len;
1350 +       dst32 = dst;
1351 +       while (rlen)
1352 +       {
1353 +           clen = XftUtf8ToUcs4 (src, &c, rlen);
1354 +           if (clen <= 0)      /* malformed UTF8 string */
1355 +               return;
1356 +           *dst32++ = c;
1357 +           src += clen;
1358 +           rlen -= clen;
1359 +       }
1360 +       dst32 = dst;
1361 +       XftTextExtents32 (dpy, font, dst32, n, extents);
1362 +       break;
1363 +    case 2:
1364 +       src = string;
1365 +       rlen = len;
1366 +       dst16 = (XftChar16 *) dst;
1367 +       while (rlen)
1368 +       {
1369 +           clen = XftUtf8ToUcs4 (src, &c, rlen);
1370 +           if (clen <= 0)      /* malformed UTF8 string */
1371 +               return;
1372 +           *dst16++ = c;
1373 +           src += clen;
1374 +           rlen -= clen;
1375 +       }
1376 +       dst16 = (XftChar16 *) dst;
1377 +       XftTextExtents16 (dpy, font, dst16, n, extents);
1378 +       break;
1379 +    case 1:
1380 +       src = string;
1381 +       rlen = len;
1382 +       dst8 = (XftChar8 *) dst;
1383 +       while (rlen)
1384 +       {
1385 +           clen = XftUtf8ToUcs4 (src, &c, rlen);
1386 +           if (clen <= 0)      /* malformed UTF8 string */
1387 +               return;
1388 +           *dst8++ = c;
1389 +           src += clen;
1390 +           rlen -= clen;
1391 +       }
1392 +       dst8 = (XftChar8 *) dst;
1393 +       XftTextExtents8 (dpy, font, dst8, n, extents);
1394 +       break;
1395 +    }
1396 +    if (dst != lbuf)
1397 +       free (dst);
1398  }
1399 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftfont.c xc/lib/Xft/xftfont.c
1400 --- XFree86-4.0.2.orig/xc/lib/Xft/xftfont.c     Sat Dec 16 12:33:01 2000
1401 +++ XFree86-4.0.2/xc/lib/Xft/xftfont.c  Fri Jan 19 20:25:58 2001
1402 @@ -1,5 +1,5 @@
1403  /*
1404 - * $XFree86: xc/lib/Xft/xftfont.c,v 1.7 2000/12/15 17:12:53 keithp Exp $
1405 + * $XFree86: xc/lib/Xft/xftfont.c,v 1.8 2000/12/20 00:20:48 keithp Exp $
1406   *
1407   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
1408   *
1409 @@ -22,9 +22,9 @@
1410   * PERFORMANCE OF THIS SOFTWARE.
1411   */
1412  
1413 +#include <stdio.h>
1414  #include <stdlib.h>
1415  #include "xftint.h"
1416 -#include <stdio.h>
1417  
1418  XftPattern *
1419  XftFontMatch (Display *dpy, int screen, XftPattern *pattern, XftResult *result)
1420 @@ -43,8 +43,24 @@
1421      new = XftPatternDuplicate (pattern);
1422      if (!new)
1423         return 0;
1424 +
1425 +    if (_XftFontDebug () & XFT_DBG_OPENV)
1426 +    {
1427 +       printf ("XftFontMatch pattern ");
1428 +       XftPatternPrint (new);
1429 +    }
1430      XftConfigSubstitute (new);
1431 +    if (_XftFontDebug () & XFT_DBG_OPENV)
1432 +    {
1433 +       printf ("XftFontMatch after XftConfig substitutions ");
1434 +       XftPatternPrint (new);
1435 +    }
1436      XftDefaultSubstitute (dpy, screen, new);
1437 +    if (_XftFontDebug () & XFT_DBG_OPENV)
1438 +    {
1439 +       printf ("XftFontMatch after X resource substitutions ");
1440 +       XftPatternPrint (new);
1441 +    }
1442      nsets = 0;
1443      
1444  #ifdef FREETYPE2
1445 @@ -52,6 +68,11 @@
1446      core = True;
1447      (void) XftPatternGetBool (new, XFT_RENDER, 0, &render);
1448      (void) XftPatternGetBool (new, XFT_CORE, 0, &core);
1449 +    if (_XftFontDebug () & XFT_DBG_OPENV)
1450 +    {
1451 +       printf ("XftFontMatch: use core fonts \"%s\", use render fonts \"%s\"\n",
1452 +               core ? "True" : "False", render ? "True" : "False");
1453 +    }
1454  
1455      if (render)
1456      {
1457 @@ -133,10 +154,17 @@
1458  
1459      if (!initialized)
1460      {
1461 +       char    *e;
1462 +       
1463         initialized = 1;
1464 -       debug = getenv ("XFT_DEBUG") != 0;
1465 -       if (debug)
1466 -           printf ("XFT_DEBUG found\n");
1467 +       e = getenv ("XFT_DEBUG");
1468 +       if (e)
1469 +       {
1470 +           printf ("XFT_DEBUG=%s\n", e);
1471 +           debug = atoi (e);
1472 +           if (debug <= 0)
1473 +               debug = 1;
1474 +       }
1475      }
1476      return debug;
1477  }
1478 @@ -155,12 +183,12 @@
1479      va_end (va);
1480      if (!pat)
1481      {
1482 -       if (_XftFontDebug ())
1483 +       if (_XftFontDebug () & XFT_DBG_OPEN)
1484             printf ("XftFontOpen: Invalid pattern argument\n");
1485         return 0;
1486      }
1487      match = XftFontMatch (dpy, screen, pat, &result);
1488 -    if (_XftFontDebug ())
1489 +    if (_XftFontDebug () & XFT_DBG_OPEN)
1490      {
1491         printf ("Pattern ");
1492         XftPatternPrint (pat);
1493 @@ -179,7 +207,7 @@
1494      font = XftFontOpenPattern (dpy, match);
1495      if (!font)
1496      {
1497 -       if (_XftFontDebug ())
1498 +       if (_XftFontDebug () & XFT_DBG_OPEN)
1499             printf ("No Font\n");
1500         XftPatternDestroy (match);
1501      }
1502 @@ -196,7 +224,7 @@
1503      XftFont   *font;
1504  
1505      pat = XftNameParse (name);
1506 -    if (_XftFontDebug ())
1507 +    if (_XftFontDebug () & XFT_DBG_OPEN)
1508      {
1509         printf ("XftFontOpenName \"%s\": ", name);
1510         if (pat)
1511 @@ -208,7 +236,7 @@
1512      if (!pat)
1513         return 0;
1514      match = XftFontMatch (dpy, screen, pat, &result);
1515 -    if (_XftFontDebug ())
1516 +    if (_XftFontDebug () & XFT_DBG_OPEN)
1517      {
1518         if (match)
1519         {
1520 @@ -238,7 +266,7 @@
1521      XftFont   *font;
1522  
1523      pat = XftXlfdParse (xlfd, False, False);
1524 -    if (_XftFontDebug ())
1525 +    if (_XftFontDebug () & XFT_DBG_OPEN)
1526      {
1527         printf ("XftFontOpenXlfd \"%s\": ", xlfd);
1528         if (pat)
1529 @@ -250,7 +278,7 @@
1530      if (!pat)
1531         return 0;
1532      match = XftFontMatch (dpy, screen, pat, &result);
1533 -    if (_XftFontDebug ())
1534 +    if (_XftFontDebug () & XFT_DBG_OPEN)
1535      {
1536         if (match)
1537         {
1538 @@ -275,7 +303,7 @@
1539  XftFontClose (Display *dpy, XftFont *font)
1540  {
1541      if (font->core)
1542 -       XFreeFont (dpy, font->u.core.font);
1543 +       XftCoreClose (dpy, font->u.core.font);
1544  #ifdef FREETYPE2
1545      else
1546         XftFreeTypeClose (dpy, font->u.ft.font);
1547 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftfreetype.c xc/lib/Xft/xftfreetype.c
1548 --- XFree86-4.0.2.orig/xc/lib/Xft/xftfreetype.c Sat Dec 16 12:33:01 2000
1549 +++ XFree86-4.0.2/xc/lib/Xft/xftfreetype.c      Fri Jan 19 20:25:58 2001
1550 @@ -1,5 +1,5 @@
1551  /*
1552 - * $XFree86: xc/lib/Xft/xftfreetype.c,v 1.5 2000/12/15 17:12:53 keithp Exp $
1553 + * $XFree86: xc/lib/Xft/xftfreetype.c,v 1.9 2001/01/02 02:46:51 keithp Exp $
1554   *
1555   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
1556   *
1557 @@ -23,6 +23,7 @@
1558   */
1559  
1560  #include <stdlib.h>
1561 +#include <stdio.h>
1562  #include "xftint.h"
1563  
1564  FT_Library  _XftFTlibrary;
1565 @@ -32,9 +33,10 @@
1566      FT_Encoding        encoding;
1567  } XftFtEncoding;
1568  
1569 -XftFtEncoding  xftFtEncoding[] = {
1570 +static XftFtEncoding xftFtEncoding[] = {
1571      { "iso10646-1",        ft_encoding_unicode, },
1572      { "iso8859-1",         ft_encoding_unicode, },
1573 +    { "apple-roman",       ft_encoding_apple_roman },
1574      { "adobe-fontspecific", ft_encoding_symbol,  },
1575      { "glyphs-fontspecific",ft_encoding_none,   },
1576  };
1577 @@ -74,7 +76,7 @@
1578  
1579      slant = XFT_SLANT_ROMAN;
1580      if (face->style_flags & FT_STYLE_FLAG_ITALIC)
1581 -       slant = (XFT_SLANT_ITALIC + XFT_SLANT_OBLIQUE) / 2;
1582 +       slant = XFT_SLANT_ITALIC;
1583  
1584      if (!XftPatternAddInteger (pat, XFT_SLANT, slant))
1585         goto bail1;
1586 @@ -98,6 +100,10 @@
1587      if (!XftPatternAddInteger (pat, XFT_INDEX, id))
1588         goto bail1;
1589      
1590 +    if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
1591 +       if (!XftPatternAddInteger (pat, XFT_SPACING, XFT_MONO))
1592 +           goto bail1;
1593 +    
1594      if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
1595      {
1596         for (i = 0; i < face->num_fixed_sizes; i++)
1597 @@ -142,41 +148,185 @@
1598      return 0;
1599  }
1600  
1601 +/*
1602 + * List of all open files (each face in a file is managed separately)
1603 + */
1604 +typedef struct _XftFtFile {
1605 +    struct _XftFtFile  *next;
1606 +    int                        ref;
1607 +    
1608 +    char               *file;
1609 +    int                        id;
1610 +
1611 +    FT_Face            face;
1612 +    FT_F26Dot6         size;
1613 +    int                        charmap;
1614 +} XftFtFile;
1615 +
1616 +static XftFtFile *_XftFtFiles;
1617 +
1618 +static XftFtFile *
1619 +_XftFreeTypeOpenFile (char *file, int id)
1620 +{
1621 +    XftFtFile  *f;
1622 +    FT_Face    face;
1623 +
1624 +    for (f = _XftFtFiles; f; f = f->next)
1625 +    {
1626 +       if (!strcmp (f->file, file) && f->id == id)
1627 +       {
1628 +           ++f->ref;
1629 +           if (_XftFontDebug () & XFT_DBG_REF)
1630 +               printf ("FontFile %s/%d matches existing (%d)\n",
1631 +                       file, id, f->ref);
1632 +           return f;
1633 +       }
1634 +    }
1635 +    if (FT_New_Face (_XftFTlibrary, file, id, &face))
1636 +       return 0;
1637 +    
1638 +    f = malloc (sizeof (XftFtFile) + strlen (file) + 1);
1639 +    if (!f)
1640 +       return 0;
1641 +    
1642 +    if (_XftFontDebug () & XFT_DBG_REF)
1643 +       printf ("FontFile %s/%d matches new\n",
1644 +               file, id);
1645 +    f->next = _XftFtFiles;
1646 +    _XftFtFiles = f;
1647 +    f->ref = 1;
1648 +    
1649 +    f->file = (char *) (f+1);
1650 +    strcpy (f->file, file);
1651 +    f->id = id;
1652 +    
1653 +    f->face = face;
1654 +    f->size = 0;
1655 +    f->charmap = -1;
1656 +    return f;
1657 +}
1658 +
1659 +Bool
1660 +XftFreeTypeSetFace (FT_Face face, FT_F26Dot6 size, int charmap)
1661 +{
1662 +    XftFtFile  *f, **prev;
1663 +    
1664 +    for (prev = &_XftFtFiles; (f = *prev); prev = &f->next)
1665 +    {
1666 +       if (f->face == face)
1667 +       {
1668 +           /* LRU */
1669 +           if (prev != &_XftFtFiles)
1670 +           {
1671 +               *prev = f->next;
1672 +               f->next = _XftFtFiles;
1673 +               _XftFtFiles = f;
1674 +           }
1675 +           if (f->size != size)
1676 +           {
1677 +               if (_XftFontDebug() & XFT_DBG_GLYPH)
1678 +                   printf ("Set face size to %d (%d)\n", 
1679 +                           (int) (size >> 6), (int) size);
1680 +               if (FT_Set_Char_Size (face, size, size, 0, 0))
1681 +                   return False;
1682 +               f->size = size;
1683 +           }
1684 +           if (f->charmap != charmap && charmap != -1)
1685 +           {
1686 +               if (_XftFontDebug() & XFT_DBG_GLYPH)
1687 +                   printf ("Set face charmap to %d\n", charmap);
1688 +               if (FT_Set_Charmap (face, face->charmaps[charmap]))
1689 +                   return False;
1690 +               f->charmap = charmap;
1691 +           }
1692 +           break;
1693 +       }
1694 +    }
1695 +    return True;
1696 +}
1697 +
1698 +static void
1699 +_XftFreeTypeCloseFile (XftFtFile *f)
1700 +{
1701 +    XftFtFile  **prev;
1702 +    
1703 +    if (--f->ref != 0)
1704 +       return;
1705 +    for (prev = &_XftFtFiles; *prev; prev = &(*prev)->next)
1706 +    {
1707 +       if (*prev == f)
1708 +       {
1709 +           *prev = f->next;
1710 +           break;
1711 +       }
1712 +    }
1713 +    FT_Done_Face (f->face);
1714 +    free (f);
1715 +}
1716 +
1717 +/*
1718 + * Cache of all glyphsets
1719 + */
1720 +typedef struct _XftFtGlyphSet {
1721 +    struct _XftFtGlyphSet   *next;
1722 +    int                            ref;
1723 +    
1724 +    XftFtFile              *file;
1725 +    Bool                   minspace;
1726 +    int                            char_width;
1727 +    
1728 +    XftFontStruct          font;
1729 +} XftFtGlyphSet;
1730 +
1731 +static XftFtGlyphSet *_XftFtGlyphSets;
1732 +
1733  XftFontStruct *
1734  XftFreeTypeOpen (Display *dpy, XftPattern *pattern)
1735  {
1736 -    char           *file;
1737 +    XftFtFile      *file;
1738 +    FT_Face        face;
1739 +    XftFtGlyphSet   *gs;
1740 +    char           *filename;
1741      int                    id;
1742 -    double         size;
1743 +    double         dsize;
1744 +    FT_F26Dot6     size;
1745      int                    rgba;
1746      int                    spacing;
1747      int                    char_width;
1748      Bool           antialias;
1749 -    Bool           encoded;
1750 +    Bool           minspace;
1751      char           *encoding_name;
1752 -    FT_Face        face;
1753      XftFontStruct   *font;
1754      int                    j;
1755      FT_Encoding            encoding;
1756      int                    charmap;
1757 -    int                    error;
1758  
1759 -    int                    height, ascent, descent;
1760      int                    extra;
1761 -    int                    div;
1762 -    
1763 +    int                    height, ascent, descent;
1764      XRenderPictFormat  pf, *format;
1765      
1766 -    if (XftPatternGetString (pattern, XFT_FILE, 0, &file) != XftResultMatch)
1767 +    /*
1768 +     * Open the file
1769 +     */
1770 +    if (XftPatternGetString (pattern, XFT_FILE, 0, &filename) != XftResultMatch)
1771         goto bail0;
1772      
1773      if (XftPatternGetInteger (pattern, XFT_INDEX, 0, &id) != XftResultMatch)
1774         goto bail0;
1775      
1776 +    file = _XftFreeTypeOpenFile (filename, id);
1777 +    if (!file)
1778 +       goto bail0;
1779 +    
1780 +    face = file->face;
1781 +
1782 +    /*
1783 +     * Extract the glyphset information from the pattern
1784 +     */
1785      if (XftPatternGetString (pattern, XFT_ENCODING, 0, &encoding_name) != XftResultMatch)
1786         goto bail0;
1787      
1788 -    if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &size) != XftResultMatch)
1789 +    if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &dsize) != XftResultMatch)
1790         goto bail0;
1791      
1792      switch (XftPatternGetInteger (pattern, XFT_RGBA, 0, &rgba)) {
1793 @@ -199,11 +349,101 @@
1794         goto bail0;
1795      }
1796      
1797 +    switch (XftPatternGetBool (pattern, XFT_MINSPACE, 0, &minspace)) {
1798 +    case XftResultNoMatch:
1799 +       minspace = False;
1800 +       break;
1801 +    case XftResultMatch:
1802 +       break;
1803 +    default:
1804 +       goto bail0;
1805 +    }
1806 +    
1807 +    switch (XftPatternGetInteger (pattern, XFT_SPACING, 0, &spacing)) {
1808 +    case XftResultNoMatch:
1809 +       spacing = XFT_PROPORTIONAL;
1810 +       break;
1811 +    case XftResultMatch:
1812 +       break;
1813 +    default:
1814 +       goto bail1;
1815 +    }
1816 +    
1817      if (XftPatternGetInteger (pattern, XFT_CHAR_WIDTH, 
1818                               0, &char_width) != XftResultMatch)
1819      {
1820         char_width = 0;
1821      }
1822 +    else if (char_width)
1823 +       spacing = XFT_MONO;
1824 +
1825 +    encoding = face->charmaps[0]->encoding;
1826 +    
1827 +    for (j = 0; j < NUM_FT_ENCODINGS; j++)
1828 +       if (!strcmp (encoding_name, xftFtEncoding[j].name))
1829 +       {
1830 +           encoding = xftFtEncoding[j].encoding;
1831 +           break;
1832 +       }
1833 +    
1834 +    size = (FT_F26Dot6) (dsize * 64.0);
1835 +    
1836 +    if (encoding == ft_encoding_none)
1837 +       charmap = -1;
1838 +    else
1839 +    {
1840 +       for (charmap = 0; charmap < face->num_charmaps; charmap++)
1841 +           if (face->charmaps[charmap]->encoding == encoding)
1842 +               break;
1843 +
1844 +       if (charmap == face->num_charmaps)
1845 +           goto bail1;
1846 +    }
1847 +
1848 +    
1849 +    /*
1850 +     * Match an existing glyphset
1851 +     */
1852 +    for (gs = _XftFtGlyphSets; gs; gs = gs->next)
1853 +    {
1854 +       if (gs->file == file &&
1855 +           gs->minspace == minspace &&
1856 +           gs->char_width == char_width &&
1857 +           gs->font.size == size &&
1858 +           gs->font.spacing == spacing &&
1859 +           gs->font.charmap == charmap &&
1860 +           gs->font.rgba == rgba &&
1861 +           gs->font.antialias == antialias)
1862 +       {
1863 +           ++gs->ref;
1864 +           if (_XftFontDebug () & XFT_DBG_REF)
1865 +           {
1866 +               printf ("Face size %g matches existing (%d)\n",
1867 +                       dsize, gs->ref);
1868 +           }
1869 +           return &gs->font;
1870 +       }
1871 +    }
1872 +    
1873 +    if (_XftFontDebug () & XFT_DBG_REF)
1874 +    {
1875 +       printf ("Face size %g matches new\n",
1876 +               dsize);
1877 +    }
1878 +    /*
1879 +     * No existing glyphset, create another
1880 +     */
1881 +    gs = malloc (sizeof (XftFtGlyphSet));
1882 +    if (!gs)
1883 +       goto bail1;
1884 +
1885 +    gs->ref = 1;
1886 +    
1887 +    gs->file = file;
1888 +    gs->minspace = minspace;
1889 +    gs->char_width = char_width;
1890 +
1891 +    font = &gs->font;
1892      
1893      if (antialias)
1894      {
1895 @@ -261,106 +501,60 @@
1896      }
1897      
1898      if (!format)
1899 -       goto bail0;
1900 +       goto bail2;
1901      
1902 -    if (FT_New_Face (_XftFTlibrary, file, id, &face))
1903 -       goto bail0;
1904 +    font->size = size;
1905  
1906 -    font = (XftFontStruct *) malloc (sizeof (XftFontStruct));
1907 -    if (!font)
1908 -       goto bail1;
1909 -    
1910 -    font->size = (FT_F26Dot6) (size * 64.0);
1911 -    
1912 -    if ( FT_Set_Char_Size (face, font->size, font->size, 0, 0) )
1913 +    if (!XftFreeTypeSetFace (face, size, charmap))
1914         goto bail2;
1915  
1916 -    encoding = face->charmaps[0]->encoding;
1917 -    
1918 -    for (j = 0; j < NUM_FT_ENCODINGS; j++)
1919 -       if (!strcmp (encoding_name, xftFtEncoding[j].name))
1920 -       {
1921 -           encoding = xftFtEncoding[j].encoding;
1922 -           break;
1923 -       }
1924 -    
1925 -    if (encoding == ft_encoding_none)
1926 -       encoded = False;
1927 -    else
1928 +    descent = -(face->size->metrics.descender >> 6);
1929 +    ascent = face->size->metrics.ascender >> 6;
1930 +    if (minspace)
1931      {
1932 -       encoded = True;
1933 -       for (charmap = 0; charmap < face->num_charmaps; charmap++)
1934 -           if (face->charmaps[charmap]->encoding == encoding)
1935 -               break;
1936 -
1937 -       if (charmap == face->num_charmaps)
1938 -           goto bail2;
1939 -
1940 -       error = FT_Set_Charmap(face,
1941 -                              face->charmaps[charmap]);
1942 -
1943 -       if (error)
1944 -           goto bail2;
1945 +       height = ascent + descent;
1946      }
1947 -    
1948 -    height = face->height;
1949 -    ascent = face->ascender;
1950 -    descent = face->descender;
1951 -    if (descent < 0) descent = - descent;
1952 -    extra = (height - (ascent + descent));
1953 -    if (extra > 0)
1954 +    else
1955      {
1956 -       ascent = ascent + extra / 2;
1957 -       descent = height - ascent;
1958 +       height = face->size->metrics.height >> 6;
1959 +       extra = (height - (ascent + descent));
1960 +       if (extra > 0)
1961 +       {
1962 +           ascent = ascent + extra / 2;
1963 +           descent = height - ascent;
1964 +       }
1965 +       else if (extra < 0)
1966 +           height = ascent + descent;
1967      }
1968 -    else if (extra < 0)
1969 -       height = ascent + descent;
1970 -    div = face->units_per_EM;
1971 -    if (height > div * 5)
1972 -       div *= 10;
1973 -    
1974 -    div = face->units_per_EM;
1975 -    if (height > div * 5)
1976 -       div *= 10;
1977 -    
1978 -    font->descent = descent * font->size / (64 * div);
1979 -    font->ascent = ascent * font->size / (64 * div);
1980 -    font->height = height * font->size / (64 * div);
1981 -    font->max_advance_width = face->max_advance_width * font->size / (64 * div);
1982 +    font->ascent = ascent;
1983 +    font->descent = descent;
1984 +    font->height = height;
1985      
1986 -    font->monospace = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0;
1987      if (char_width)
1988 -    {
1989         font->max_advance_width = char_width;
1990 -       font->monospace = True;
1991 -    }
1992 -    switch (XftPatternGetInteger (pattern, XFT_SPACING, 0, &spacing)) {
1993 -    case XftResultNoMatch:
1994 -       break;
1995 -    case XftResultMatch:
1996 -       if (spacing != XFT_PROPORTIONAL)
1997 -           font->monospace = True;
1998 -       break;
1999 -    default:
2000 -       goto bail2;
2001 -    }
2002 +    else
2003 +       font->max_advance_width = face->size->metrics.max_advance >> 6;
2004 +    
2005 +    gs->next = _XftFtGlyphSets;
2006 +    _XftFtGlyphSets = gs;
2007      
2008      font->glyphset = XRenderCreateGlyphSet (dpy, format);
2009  
2010 +    font->spacing = spacing;
2011      font->format = format;
2012      font->realized =0;
2013      font->nrealized = 0;
2014      font->rgba = rgba;
2015      font->antialias = antialias;
2016 -    font->encoded = encoded;
2017 +    font->charmap = charmap;
2018      font->face = face;
2019  
2020      return font;
2021      
2022  bail2:
2023 -    free (font);
2024 +    free (gs);
2025  bail1:
2026 -    FT_Done_Face (font->face);
2027 +    _XftFreeTypeCloseFile (file);
2028  bail0:
2029      return 0;
2030  }
2031 @@ -368,10 +562,26 @@
2032  void
2033  XftFreeTypeClose (Display *dpy, XftFontStruct *font)
2034  {
2035 -    XRenderFreeGlyphSet (dpy, font->glyphset);
2036 -    if (font->realized)
2037 -       free (font->realized);
2038 -    FT_Done_Face (font->face);
2039 +    XftFtGlyphSet   *gs, **prev;
2040 +
2041 +    for (prev = &_XftFtGlyphSets; (gs = *prev); prev = &gs->next)
2042 +    {
2043 +       if (&gs->font == font)
2044 +       {
2045 +           if (--gs->ref == 0)
2046 +           {
2047 +               XRenderFreeGlyphSet (dpy, font->glyphset);
2048 +               if (font->realized)
2049 +                   free (font->realized);
2050 +               
2051 +               _XftFreeTypeCloseFile (gs->file);
2052 +
2053 +               *prev = gs->next;
2054 +               free (gs);
2055 +           }
2056 +           break;
2057 +       }
2058 +    }
2059  }
2060                   
2061  XftFontStruct *
2062 @@ -388,6 +598,7 @@
2063  XftInitFtLibrary (void)
2064  {
2065      char    **d;
2066 +    char    *cache;
2067      
2068      if (_XftFTlibrary)
2069         return True;
2070 @@ -396,16 +607,21 @@
2071      _XftFontSet = XftFontSetCreate ();
2072      if (!_XftFontSet)
2073         return False;
2074 +    cache = XftConfigGetCache ();
2075 +    if (cache)
2076 +       XftFileCacheLoad (cache);
2077      for (d = XftConfigDirs; d && *d; d++)
2078      {
2079  #ifdef XFT_DEBUG_FONTSET
2080         printf ("scan dir %s\n", *d);
2081  #endif
2082 -       XftDirScan (_XftFontSet, *d);
2083 +       XftDirScan (_XftFontSet, *d, False);
2084      }
2085  #ifdef XFT_DEBUG_FONTSET
2086      XftPrintFontSet (_XftFontSet);
2087  #endif
2088 +    if (cache)
2089 +       XftFileCacheSave (cache);
2090 +    XftFileCacheDispose ();
2091      return True;
2092  }
2093 -
2094 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftglyphs.c xc/lib/Xft/xftglyphs.c
2095 --- XFree86-4.0.2.orig/xc/lib/Xft/xftglyphs.c   Sat Dec 16 12:33:01 2000
2096 +++ XFree86-4.0.2/xc/lib/Xft/xftglyphs.c        Fri Jan 19 20:25:58 2001
2097 @@ -1,5 +1,5 @@
2098  /*
2099 - * $XFree86: xc/lib/Xft/xftglyphs.c,v 1.6 2000/12/15 17:12:53 keithp Exp $
2100 + * $XFree86: xc/lib/Xft/xftglyphs.c,v 1.8 2000/12/22 02:25:41 keithp Exp $
2101   *
2102   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2103   *
2104 @@ -22,6 +22,7 @@
2105   * PERFORMANCE OF THIS SOFTWARE.
2106   */
2107  
2108 +#include <stdio.h>
2109  #include <stdlib.h>
2110  #include "xftint.h"
2111  #include <freetype/ftoutln.h>
2112 @@ -73,6 +74,9 @@
2113      FT_Bitmap      ftbit;
2114      FT_Matrix      matrix;
2115  
2116 +    if (!XftFreeTypeSetFace (font->face, font->size, font->charmap))
2117 +       return ;
2118 +
2119      if (font->antialias && font->rgba)
2120      {
2121         matrix.xx = 0x30000L;
2122 @@ -87,11 +91,16 @@
2123         if (!gi)
2124             continue;
2125         
2126 -       if (font->encoded)
2127 +       if (font->charmap != -1)
2128         {
2129             glyphindex = FT_Get_Char_Index (font->face, charcode);
2130             if (!glyphindex)
2131 +           {
2132 +               if (_XftFontDebug() & XFT_DBG_GLYPH)
2133 +                   printf ("glyph (%c) %d missing\n",
2134 +                           (int) charcode, (int) charcode);
2135                 continue;
2136 +           }
2137         }
2138         else
2139             glyphindex = (FT_UInt) charcode;
2140 @@ -112,7 +121,7 @@
2141         /*
2142          * Try to keep monospace fonts ink-inside
2143          */
2144 -       if (font->monospace)
2145 +       if (font->spacing != XFT_PROPORTIONAL)
2146         {
2147             if (TRUNC(right) > font->max_advance_width)
2148             {
2149 @@ -192,39 +201,42 @@
2150                     }
2151                 }
2152             }
2153 -#if 0
2154 +           if (_XftFontDebug() & XFT_DBG_GLYPH)
2155             {
2156 -               int             x, y;
2157 -               unsigned char   *line;
2158 -
2159 -               line = bufBitmap;
2160 -               printf ("\nchar 0x%x (%c):\n", (int) charcode, (char) charcode);
2161 -               for (y = 0; y < height; y++)
2162 +               printf ("char 0x%x (%c):\n", (int) charcode, (char) charcode);
2163 +               if (_XftFontDebug() & XFT_DBG_GLYPHV)
2164                 {
2165 -                   if (font->antialias) 
2166 -                   {
2167 -                       static char    den[] = { " .:;=+*#" };
2168 -                       for (x = 0; x < pitch; x++)
2169 -                           printf ("%c", den[line[x] >> 5]);
2170 -                   }
2171 -                   else
2172 +                   int         x, y;
2173 +                   unsigned char       *line;
2174 +
2175 +                   line = bufBitmap;
2176 +                   for (y = 0; y < height; y++)
2177                     {
2178 -                       for (x = 0; x < pitch * 8; x++)
2179 +                       if (font->antialias) 
2180                         {
2181 -                           printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
2182 +                           static char    den[] = { " .:;=+*#" };
2183 +                           for (x = 0; x < pitch; x++)
2184 +                               printf ("%c", den[line[x] >> 5]);
2185                         }
2186 +                       else
2187 +                       {
2188 +                           for (x = 0; x < pitch * 8; x++)
2189 +                           {
2190 +                               printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
2191 +                           }
2192 +                       }
2193 +                       printf ("\n");
2194 +                       line += pitch;
2195                     }
2196                     printf ("\n");
2197 -                   line += pitch;
2198                 }
2199             }
2200 -#endif
2201         }
2202         else
2203         {
2204 -#if 0
2205 -           printf ("glyph (%c) %d missing\n", (int) charcode, (int) charcode);
2206 -#endif
2207 +           if (_XftFontDebug() & XFT_DBG_GLYPH)
2208 +               printf ("glyph (%c) %d no outline\n",
2209 +                       (int) charcode, (int) charcode);
2210             continue;
2211         }
2212         
2213 @@ -232,7 +244,7 @@
2214         gi->height = height;
2215         gi->x = -TRUNC(left);
2216         gi->y = TRUNC(top);
2217 -       if (font->monospace)
2218 +       if (font->spacing != XFT_PROPORTIONAL)
2219             gi->xOff = font->max_advance_width;
2220         else
2221             gi->xOff = TRUNC(ROUND(glyph->metrics.horiAdvance));
2222 @@ -368,7 +380,10 @@
2223                         XftFontStruct   *font,
2224                         XftChar32       glyph)
2225  {
2226 -    if (font->encoded)
2227 +    if (font->charmap != -1)
2228 +    {
2229 +       FT_Set_Charmap (font->face, font->face->charmaps[font->charmap]);
2230         glyph = (XftChar32) FT_Get_Char_Index (font->face, (FT_ULong) glyph);
2231 +    }
2232      return glyph && glyph <= font->face->num_glyphs;
2233  }
2234 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftgram.y xc/lib/Xft/xftgram.y
2235 --- XFree86-4.0.2.orig/xc/lib/Xft/xftgram.y     Thu Nov 30 18:30:00 2000
2236 +++ XFree86-4.0.2/xc/lib/Xft/xftgram.y  Fri Jan 19 20:25:58 2001
2237 @@ -1,5 +1,5 @@
2238  /*
2239 - * $XFree86: xc/lib/Xft/xftgram.y,v 1.2 2000/11/30 23:30:00 dawes Exp $
2240 + * $XFree86: xc/lib/Xft/xftgram.y,v 1.3 2001/01/02 02:46:51 keithp Exp $
2241   *
2242   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2243   *
2244 @@ -47,7 +47,8 @@
2245  %token <dval>  DOUBLE
2246  %token <sval>  STRING NAME
2247  %token <ival>  ANY ALL
2248 -%token <ival>  DIR INCLUDE INCLUDEIF MATCH EDIT TOK_TRUE TOK_FALSE TOK_NIL
2249 +%token <ival>  DIR CACHE INCLUDE INCLUDEIF MATCH EDIT
2250 +%token <ival>  TOK_TRUE TOK_FALSE TOK_NIL
2251  %token <ival>  EQUAL SEMI
2252  
2253  %type  <eval>  expr
2254 @@ -75,6 +76,8 @@
2255         ;
2256  config :   DIR STRING
2257                 { XftConfigAddDir ($2); }
2258 +       |   CACHE STRING
2259 +               { XftConfigSetCache ($2); }
2260         |   INCLUDE STRING
2261                 { XftConfigPushInput ($2, True); }
2262         |   INCLUDEIF STRING
2263 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftint.h xc/lib/Xft/xftint.h
2264 --- XFree86-4.0.2.orig/xc/lib/Xft/xftint.h      Sat Dec 16 12:33:01 2000
2265 +++ XFree86-4.0.2/xc/lib/Xft/xftint.h   Fri Jan 19 20:25:58 2001
2266 @@ -1,5 +1,5 @@
2267  /*
2268 - * $XFree86: xc/lib/Xft/xftint.h,v 1.15 2000/12/15 17:12:53 keithp Exp $
2269 + * $XFree86: xc/lib/Xft/xftint.h,v 1.20 2001/01/02 02:46:51 keithp Exp $
2270   *
2271   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2272   *
2273 @@ -84,6 +84,16 @@
2274  #define XFT_DEFAULT_PATH "/usr/X11R6/lib/X11/XftConfig"
2275  #endif
2276  
2277 +#define XFT_DBG_OPEN   1
2278 +#define XFT_DBG_OPENV  2
2279 +#define XFT_DBG_RENDER 4
2280 +#define XFT_DBG_DRAW   8
2281 +#define XFT_DBG_REF    16
2282 +#define XFT_DBG_GLYPH  32
2283 +#define XFT_DBG_GLYPHV 64
2284 +#define XFT_DBG_CACHE  128
2285 +#define XFT_DBG_CACHEV 256
2286 +
2287  typedef enum _XftOp {
2288      XftOpInteger, XftOpDouble, XftOpString, XftOpBool, XftOpNil,
2289      XftOpField,
2290 @@ -191,11 +201,40 @@
2291  }
2292  
2293  
2294 +/* xftcache.c */
2295 +
2296 +char *
2297 +XftFileCacheFind (char *file, int id, int *count);
2298 +
2299 +void
2300 +XftFileCacheDispose (void);
2301 +
2302 +void
2303 +XftFileCacheLoad (char *cache);
2304 +
2305 +Bool
2306 +XftFileCacheUpdate (char *file, int id, char *name);
2307 +
2308 +Bool
2309 +XftFileCacheSave (char *cache);
2310 +
2311 +Bool
2312 +XftFileCacheReadDir (XftFontSet *set, const char *cache_file);
2313 +
2314 +Bool
2315 +XftFileCacheWriteDir (XftFontSet *set, const char *cache_file);
2316 +    
2317  /* xftcfg.c */
2318  Bool
2319  XftConfigAddDir (char *d);
2320  
2321  Bool
2322 +XftConfigSetCache (char *c);
2323 +
2324 +char *
2325 +XftConfigGetCache (void);
2326 +
2327 +Bool
2328  XftConfigAddEdit (XftTest *test, XftEdit *edit);
2329  
2330  Bool
2331 @@ -217,6 +256,12 @@
2332                   int               len,
2333                   XChar2b           xcloc[XFT_CORE_N16LOCAL]);
2334  
2335 +XChar2b *
2336 +XftCoreConvertUtf8 (XftChar8   *string,
2337 +                   int         len,
2338 +                   XChar2b     xcloc[XFT_CORE_N16LOCAL],
2339 +                   int         *nchar);
2340 +
2341  void
2342  XftCoreExtents8 (Display       *dpy,
2343                  XFontStruct    *fs,
2344 @@ -238,6 +283,13 @@
2345                   int               len,
2346                   XGlyphInfo        *extents);
2347  
2348 +void
2349 +XftCoreExtentsUtf8 (Display        *dpy,
2350 +                   XFontStruct     *fs,
2351 +                   XftChar8        *string, 
2352 +                   int             len,
2353 +                   XGlyphInfo      *extents);
2354 +
2355  Bool
2356  XftCoreGlyphExists (Display        *dpy,
2357                     XFontStruct     *fs,
2358 @@ -259,10 +311,6 @@
2359  void
2360  XftSubstPrint (XftSubst *subst);
2361  
2362 -/* xftdir.c */
2363 -Bool
2364 -XftDirScan (XftFontSet *set, const char *dir);
2365 -
2366  /* xftdpy.c */
2367  int
2368  XftDefaultParseBool (char *v);
2369 @@ -295,12 +343,7 @@
2370  int
2371  _XftFontDebug (void);
2372      
2373 -/* xftfreetype.c */
2374 -XftPattern *
2375 -XftFreeTypeQuery (const char *file, int id, int *count);
2376 -
2377  /* xftfs.c */
2378 -/* xftglyphs.c */
2379  /* xftgram.y */
2380  int
2381  XftConfigparse (void);
2382 @@ -349,7 +392,7 @@
2383  
2384  /* xftinit.c */
2385  Bool
2386 -XftInitFtLibrary (void);
2387 +XftInit (char *config);
2388  
2389  /* xftlex.l */
2390  extern int     XftConfigLineno;
2391 @@ -365,9 +408,6 @@
2392  XftConfigPushInput (char *s, Bool complain);
2393  
2394  /* xftlist.c */
2395 -XftObjectSet *
2396 -_XftObjectSetVapBuild (const char *first, va_list *vap);
2397 -
2398  Bool
2399  XftListValueCompare (XftValue  v1,
2400                      XftValue   v2);
2401 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftlex.l xc/lib/Xft/xftlex.l
2402 --- XFree86-4.0.2.orig/xc/lib/Xft/xftlex.l      Sat Dec 16 12:33:01 2000
2403 +++ XFree86-4.0.2/xc/lib/Xft/xftlex.l   Fri Jan 19 20:25:58 2001
2404 @@ -1,6 +1,6 @@
2405  %{
2406  /*
2407 - * $XFree86: xc/lib/Xft/xftlex.l,v 1.3 2000/12/15 22:48:39 dawes Exp $
2408 + * $XFree86: xc/lib/Xft/xftlex.l,v 1.4 2001/01/02 02:46:51 keithp Exp $
2409   *
2410   * Copyright (c) 2000 Keith Packard, member of The XFree86 Project, Inc.
2411   *
2412 @@ -97,6 +97,7 @@
2413  "/\052"                _XftConfigSkipComment();
2414  ^#             _XftConfigSkipLine();
2415  dir            return DIR;
2416 +cache          return CACHE;
2417  include                return INCLUDE;
2418  includeif      return INCLUDEIF;
2419  match          return MATCH;
2420 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftname.c xc/lib/Xft/xftname.c
2421 --- XFree86-4.0.2.orig/xc/lib/Xft/xftname.c     Sat Dec 16 12:33:00 2000
2422 +++ XFree86-4.0.2/xc/lib/Xft/xftname.c  Fri Jan 19 20:25:58 2001
2423 @@ -1,5 +1,5 @@
2424  /*
2425 - * $XFree86: xc/lib/Xft/xftname.c,v 1.5 2000/12/14 23:03:56 keithp Exp $
2426 + * $XFree86: xc/lib/Xft/xftname.c,v 1.8 2001/01/02 02:46:51 keithp Exp $
2427   *
2428   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2429   *
2430 @@ -26,13 +26,14 @@
2431  #include <ctype.h>
2432  #include <stdlib.h>
2433  #include <string.h>
2434 +#include <stdio.h>
2435  
2436  typedef struct _XftObjectType {
2437      const char *object;
2438      XftType    type;
2439  } XftObjectType;
2440  
2441 -const XftObjectType _XftObjectTypes[] = {
2442 +static const XftObjectType _XftObjectTypes[] = {
2443      { XFT_FAMILY,      XftTypeString, },
2444      { XFT_STYLE,       XftTypeString, },
2445      { XFT_SLANT,       XftTypeInteger, },
2446 @@ -53,6 +54,9 @@
2447      { XFT_RGBA,                XftTypeInteger, },
2448      { XFT_SCALE,       XftTypeDouble, },
2449      { XFT_RENDER,      XftTypeBool, },
2450 +    { XFT_MINSPACE,    XftTypeBool, },
2451 +    { XFT_CHAR_WIDTH,  XftTypeInteger },
2452 +    { XFT_CHAR_HEIGHT, XftTypeInteger },
2453  };
2454  
2455  #define NUM_OBJECT_TYPES    (sizeof _XftObjectTypes / sizeof _XftObjectTypes[0])
2456 @@ -152,9 +156,17 @@
2457  {
2458      char    c;
2459      
2460 -    while (*cur && !strchr (delim, *cur))
2461 +    while ((c = *cur))
2462      {
2463 -       c = *cur++;
2464 +       if (c == '\\')
2465 +       {
2466 +           ++cur;
2467 +           if (!(c = *cur))
2468 +               break;
2469 +       }
2470 +       else if (strchr (delim, c))
2471 +           break;
2472 +       ++cur;
2473         *save++ = c;
2474      }
2475      *save = 0;
2476 @@ -211,10 +223,10 @@
2477      }
2478      while (delim == ':')
2479      {
2480 -       name = _XftNameFindNext (name, "=-:", save, &delim);
2481 +       name = _XftNameFindNext (name, "=_:", save, &delim);
2482         if (save[0])
2483         {
2484 -           if (delim == '=' || delim == '-')
2485 +           if (delim == '=' || delim == '_')
2486             {
2487                 t = XftNameGetType (save);
2488                 for (;;)
2489 @@ -250,4 +262,118 @@
2490      free (save);
2491  bail0:
2492      return 0;
2493 +}
2494 +
2495 +static Bool
2496 +_XftNameUnparseString (const char *string, char *escape, char **destp, int *lenp)
2497 +{
2498 +    int            len = *lenp;
2499 +    char    *dest = *destp;
2500 +    char    c;
2501 +
2502 +    while ((c = *string++))
2503 +    {
2504 +       if (escape && strchr (escape, c))
2505 +       {
2506 +           if (len-- == 0)
2507 +               return False;
2508 +           *dest++ = escape[0];
2509 +       }
2510 +       if (len-- == 0)
2511 +           return False;
2512 +       *dest++ = c;
2513 +    }
2514 +    *destp = dest;
2515 +    *lenp = len;
2516 +    return True;
2517 +}
2518 +
2519 +static Bool
2520 +_XftNameUnparseValue (XftValue v, char *escape, char **destp, int *lenp)
2521 +{
2522 +    char    temp[1024];
2523 +    
2524 +    switch (v.type) {
2525 +    case XftTypeVoid:
2526 +       return True;
2527 +    case XftTypeInteger:
2528 +       sprintf (temp, "%d", v.u.i);
2529 +       return _XftNameUnparseString (temp, 0, destp, lenp);
2530 +    case XftTypeDouble:
2531 +       sprintf (temp, "%g", v.u.d);
2532 +       return _XftNameUnparseString (temp, 0, destp, lenp);
2533 +    case XftTypeString:
2534 +       return _XftNameUnparseString (v.u.s, escape, destp, lenp);
2535 +    case XftTypeBool:
2536 +       return _XftNameUnparseString (v.u.b ? "True" : "False", 0, destp, lenp);
2537 +    }
2538 +    return False;
2539 +}
2540 +
2541 +static Bool
2542 +_XftNameUnparseValueList (XftValueList *v, char *escape, char **destp, int *lenp)
2543 +{
2544 +    while (v)
2545 +    {
2546 +       if (!_XftNameUnparseValue (v->value, escape, destp, lenp))
2547 +           return False;
2548 +       if ((v = v->next))
2549 +           if (!_XftNameUnparseString (",", 0, destp, lenp))
2550 +               return False;
2551 +    }
2552 +    return True;
2553 +}
2554 +
2555 +#define XFT_ESCAPE_FIXED    "\\-:,"
2556 +#define XFT_ESCAPE_VARIABLE "\\=_:,"
2557 +
2558 +Bool
2559 +XftNameUnparse (XftPattern *pat, char *dest, int len)
2560 +{
2561 +    int                        i;
2562 +    XftPatternElt      *e;
2563 +    const XftObjectType *o;
2564 +
2565 +    e = XftPatternFind (pat, XFT_FAMILY, False);
2566 +    if (e)
2567 +    {
2568 +       if (!_XftNameUnparseValueList (e->values, XFT_ESCAPE_FIXED,
2569 +                                      &dest, &len))
2570 +           return False;
2571 +    }
2572 +    e = XftPatternFind (pat, XFT_SIZE, False);
2573 +    if (e)
2574 +    {
2575 +       if (!_XftNameUnparseString ("-", 0, &dest, &len))
2576 +           return False;
2577 +       if (!_XftNameUnparseValueList (e->values, XFT_ESCAPE_FIXED, &dest, &len))
2578 +           return False;
2579 +    }
2580 +    for (i = 0; i < NUM_OBJECT_TYPES; i++)
2581 +    {
2582 +       o = &_XftObjectTypes[i];
2583 +       if (!strcmp (o->object, XFT_FAMILY) || 
2584 +           !strcmp (o->object, XFT_SIZE) ||
2585 +           !strcmp (o->object, XFT_FILE))
2586 +           continue;
2587 +       
2588 +       e = XftPatternFind (pat, o->object, False);
2589 +       if (e)
2590 +       {
2591 +           if (!_XftNameUnparseString (":", 0, &dest, &len))
2592 +               return False;
2593 +           if (!_XftNameUnparseString (o->object, XFT_ESCAPE_VARIABLE, 
2594 +                                       &dest, &len))
2595 +               return False;
2596 +           if (!_XftNameUnparseString ("=", 0, &dest, &len))
2597 +               return False;
2598 +           if (!_XftNameUnparseValueList (e->values, XFT_ESCAPE_VARIABLE, 
2599 +                                          &dest, &len))
2600 +               return False;
2601 +       }
2602 +    }
2603 +    if (len == 0)
2604 +       return False;
2605 +    *dest = '\0';
2606 +    return True;
2607  }
2608 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftrender.c xc/lib/Xft/xftrender.c
2609 --- XFree86-4.0.2.orig/xc/lib/Xft/xftrender.c   Fri Dec  8 02:51:28 2000
2610 +++ XFree86-4.0.2/xc/lib/Xft/xftrender.c        Fri Jan 19 20:25:58 2001
2611 @@ -1,5 +1,5 @@
2612  /*
2613 - * $XFree86: xc/lib/Xft/xftrender.c,v 1.5 2000/12/08 07:51:28 keithp Exp $
2614 + * $XFree86: xc/lib/Xft/xftrender.c,v 1.6 2000/12/20 00:28:45 keithp Exp $
2615   *
2616   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2617   *
2618 @@ -22,6 +22,7 @@
2619   * PERFORMANCE OF THIS SOFTWARE.
2620   */
2621  
2622 +#include <stdlib.h>
2623  #include "xftint.h"
2624  
2625  void
2626 @@ -97,6 +98,93 @@
2627  }
2628  
2629  void
2630 +XftRenderStringUtf8 (Display *dpy, Picture src, 
2631 +                    XftFontStruct *font, Picture dst,
2632 +                    int srcx, int srcy,
2633 +                    int x, int y,
2634 +                    XftChar8 *string, int len)
2635 +{
2636 +    XftChar8   *s;
2637 +    XftChar32  c;
2638 +    XftChar32  lbuf[4096];
2639 +    XftChar32  *d;
2640 +    XftChar8   *dst8;
2641 +    XftChar16  *dst16;
2642 +    XftChar32  *dst32;
2643 +    int                rlen, clen;
2644 +    int                width = 1;
2645 +    int                n;
2646 +
2647 +    /* compute needed width */
2648 +    if (!XftUtf8Len (string, len, &n, &width))
2649 +       return;
2650 +    
2651 +    d = lbuf;
2652 +    if (n * width > sizeof (lbuf))
2653 +    {
2654 +       d = (XftChar32 *) malloc (n * width);
2655 +       if (!d)
2656 +           return;
2657 +    }
2658 +    
2659 +    switch (width) {
2660 +    case 4:
2661 +       s = string;
2662 +       rlen = len;
2663 +       dst32 = d;
2664 +       while (rlen)
2665 +       {
2666 +           clen = XftUtf8ToUcs4 (s, &c, rlen);
2667 +           if (clen <= 0)      /* malformed UTF8 string */
2668 +               return;
2669 +           *dst32++ = c;
2670 +           s += clen;
2671 +           rlen -= clen;
2672 +       }
2673 +       dst32 = d;
2674 +       XftRenderString32 (dpy, src, font, dst, srcx, srcy, x, y,
2675 +                        dst32, n);
2676 +       break;
2677 +    case 2:
2678 +       s = string;
2679 +       rlen = len;
2680 +       dst16 = (XftChar16 *) d;
2681 +       while (rlen)
2682 +       {
2683 +           clen = XftUtf8ToUcs4 (s, &c, rlen);
2684 +           if (clen <= 0)      /* malformed UTF8 string */
2685 +               return;
2686 +           *dst16++ = c;
2687 +           s += clen;
2688 +           rlen -= clen;
2689 +       }
2690 +       dst16 = (XftChar16 *) d;
2691 +       XftRenderString16 (dpy, src, font, dst, srcx, srcy, x, y,
2692 +                          dst16, n);
2693 +       break;
2694 +    case 1:
2695 +       s = string;
2696 +       rlen = len;
2697 +       dst8 = (XftChar8 *) d;
2698 +       while (rlen)
2699 +       {
2700 +           clen = XftUtf8ToUcs4 (s, &c, rlen);
2701 +           if (clen <= 0)      /* malformed UTF8 string */
2702 +               return;
2703 +           *dst8++ = c;
2704 +           s += clen;
2705 +           rlen -= clen;
2706 +       }
2707 +       dst8 = (XftChar8 *) d;
2708 +       XftRenderString8 (dpy, src, font, dst, srcx, srcy, x, y,
2709 +                         dst8, n);
2710 +       break;
2711 +    }
2712 +    if (d != lbuf)
2713 +       free (d);
2714 +}
2715 +   
2716 +void
2717  XftRenderExtents8 (Display         *dpy,
2718                    XftFontStruct    *font,
2719                    XftChar8    *string, 
2720 @@ -273,6 +361,89 @@
2721      while (len--)
2722      {
2723         c = *string++;
2724 +       gi = c < font->nrealized ? font->realized[c] : 0;
2725 +       if (!gi)
2726 +           continue;
2727 +       if (gi->x + x < extents->x)
2728 +           extents->x = gi->x + x;
2729 +       if (gi->y + y < extents->y)
2730 +           extents->y = gi->y + y;
2731 +       if (gi->width + x > extents->width)
2732 +           extents->width = gi->width + x;
2733 +       if (gi->height + y > extents->height)
2734 +           extents->height = gi->height + y;
2735 +       x += gi->xOff;
2736 +       y += gi->yOff;
2737 +    }
2738 +    extents->xOff = x;
2739 +    extents->yOff = y;
2740 +}
2741 +
2742 +void
2743 +XftRenderExtentsUtf8 (Display      *dpy,
2744 +                     XftFontStruct *font,
2745 +                     XftChar8      *string, 
2746 +                     int           len,
2747 +                     XGlyphInfo    *extents)
2748 +{
2749 +    unsigned int    missing[XFT_NMISSING];
2750 +    int                    nmissing;
2751 +    XftChar8       *s;
2752 +    XftChar32      c;
2753 +    int                    l, clen;
2754 +    XGlyphInfo     *gi;
2755 +    int                    x, y;
2756 +
2757 +    s = string;
2758 +    l = len;
2759 +    nmissing = 0;
2760 +    while (l)
2761 +    {
2762 +       clen = XftUtf8ToUcs4 (s, &c, l);
2763 +       if (clen < 0)
2764 +           break;
2765 +       XftGlyphCheck (dpy, font, c, missing, &nmissing);
2766 +       s += clen;
2767 +       l -= clen;
2768 +    }
2769 +    if (nmissing)
2770 +       XftGlyphLoad (dpy, font, missing, nmissing);
2771 +    
2772 +    gi = 0;
2773 +    while (len)
2774 +    {
2775 +       clen = XftUtf8ToUcs4 (string, &c, len);
2776 +       if (clen < 0)
2777 +       {
2778 +           len = 0;
2779 +           break;
2780 +       }
2781 +       len -= clen;
2782 +       string += clen;
2783 +       gi = c < font->nrealized ? font->realized[c] : 0;
2784 +       if (gi)
2785 +           break;
2786 +    }
2787 +    if (len == 0 && !gi)
2788 +    {
2789 +       extents->width = 0;
2790 +       extents->height = 0;
2791 +       extents->x = 0;
2792 +       extents->y = 0;
2793 +       extents->yOff = 0;
2794 +       extents->xOff = 0;
2795 +       return;
2796 +    }
2797 +    *extents = *gi;
2798 +    x = gi->xOff;
2799 +    y = gi->yOff;
2800 +    while (len)
2801 +    {
2802 +       clen = XftUtf8ToUcs4 (string, &c, len);
2803 +       if (clen < 0)
2804 +           break;
2805 +       len -= clen;
2806 +       string += clen;
2807         gi = c < font->nrealized ? font->realized[c] : 0;
2808         if (!gi)
2809             continue;
2810 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftstr.c xc/lib/Xft/xftstr.c
2811 --- XFree86-4.0.2.orig/xc/lib/Xft/xftstr.c      Sat Dec 16 12:33:00 2000
2812 +++ XFree86-4.0.2/xc/lib/Xft/xftstr.c   Fri Jan 19 20:25:58 2001
2813 @@ -1,5 +1,5 @@
2814  /*
2815 - * $XFree86: xc/lib/Xft/xftstr.c,v 1.2 2000/12/14 23:03:57 keithp Exp $
2816 + * $XFree86: xc/lib/Xft/xftstr.c,v 1.4 2000/12/20 10:24:27 keithp Exp $
2817   *
2818   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2819   *
2820 @@ -149,4 +149,108 @@
2821             break;
2822      }
2823      return (int) c2 - (int) c1;
2824 +}
2825 +
2826 +int
2827 +XftUtf8ToUcs4 (XftChar8    *src_orig,
2828 +              XftChar32   *dst,
2829 +              int          len)
2830 +{
2831 +    XftChar8   *src = src_orig;
2832 +    XftChar8   s;
2833 +    int                extra;
2834 +    XftChar32  result;
2835 +
2836 +    if (len == 0)
2837 +       return 0;
2838 +    
2839 +    s = *src++;
2840 +    len--;
2841 +    
2842 +    if (!(s & 0x80))
2843 +    {
2844 +       result = s;
2845 +       extra = 0;
2846 +    } 
2847 +    else if (!(s & 0x40))
2848 +    {
2849 +       return -1;
2850 +    }
2851 +    else if (!(s & 0x20))
2852 +    {
2853 +       result = s & 0x1f;
2854 +       extra = 1;
2855 +    }
2856 +    else if (!(s & 0x10))
2857 +    {
2858 +       result = s & 0xf;
2859 +       extra = 2;
2860 +    }
2861 +    else if (!(s & 0x08))
2862 +    {
2863 +       result = s & 0x07;
2864 +       extra = 3;
2865 +    }
2866 +    else if (!(s & 0x04))
2867 +    {
2868 +       result = s & 0x03;
2869 +       extra = 4;
2870 +    }
2871 +    else if ( ! (s & 0x02))
2872 +    {
2873 +       result = s & 0x01;
2874 +       extra = 5;
2875 +    }
2876 +    else
2877 +    {
2878 +       return -1;
2879 +    }
2880 +    if (extra > len)
2881 +       return -1;
2882 +    
2883 +    while (extra--)
2884 +    {
2885 +       result <<= 6;
2886 +       s = *src++;
2887 +       
2888 +       if ((s & 0xc0) != 0x80)
2889 +           return -1;
2890 +       
2891 +       result |= s & 0x3f;
2892 +    }
2893 +    *dst = result;
2894 +    return src - src_orig;
2895 +}
2896 +
2897 +Bool
2898 +XftUtf8Len (XftChar8   *string,
2899 +           int         len,
2900 +           int         *nchar,
2901 +           int         *wchar)
2902 +{
2903 +    int                n;
2904 +    int                clen;
2905 +    int                width = 1;
2906 +    XftChar32  c;
2907 +    
2908 +    n = 0;
2909 +    while (len)
2910 +    {
2911 +       clen = XftUtf8ToUcs4 (string, &c, len);
2912 +       if (clen <= 0)  /* malformed UTF8 string */
2913 +           return False;
2914 +       if (c >= 0x10000)
2915 +           width = 4;
2916 +       else if (c >= 0x100)
2917 +       {
2918 +           if (width == 1)
2919 +               width = 2;
2920 +       }
2921 +       string += clen;
2922 +       len -= clen;
2923 +       n++;
2924 +    }
2925 +    *nchar = n;
2926 +    *wchar = width;
2927 +    return True;
2928  }
2929 diff -urN -x CVS xc-4.0.2.orig/lib/Xft/xftxlfd.c xc/lib/Xft/xftxlfd.c
2930 --- XFree86-4.0.2.orig/xc/lib/Xft/xftxlfd.c     Sat Dec 16 12:33:00 2000
2931 +++ XFree86-4.0.2/xc/lib/Xft/xftxlfd.c  Fri Jan 19 20:25:58 2001
2932 @@ -1,5 +1,5 @@
2933  /*
2934 - * $XFree86: xc/lib/Xft/xftxlfd.c,v 1.5 2000/12/14 23:03:57 keithp Exp $
2935 + * $XFree86: xc/lib/Xft/xftxlfd.c,v 1.7 2000/12/22 05:05:16 tsi Exp $
2936   *
2937   * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
2938   *
2939 @@ -208,9 +208,21 @@
2940      return ret;
2941  }
2942  
2943 -XFontStruct *
2944 +typedef struct _XftCoreFont {
2945 +    struct _XftCoreFont        *next;
2946 +    int                        ref;
2947 +
2948 +    XFontStruct                *font;
2949 +    Display            *display;
2950 +    char               *xlfd;
2951 +} XftCoreFont;
2952 +
2953 +static XftCoreFont *_XftCoreFonts;
2954 +
2955 +XFontStruct*
2956  XftCoreOpen (Display *dpy, XftPattern *pattern)
2957  {
2958 +    XftCoreFont        *cf;
2959      char       *xlfd;
2960      char       *xlfd_pixel = 0;
2961      char       *i, *o;
2962 @@ -258,9 +270,66 @@
2963             xlfd = xlfd_pixel;
2964         }
2965      }
2966 -    ret = XLoadQueryFont (dpy, xlfd);
2967 +    for (cf = _XftCoreFonts; cf; cf = cf->next)
2968 +    {
2969 +       if (cf->display == dpy &&
2970 +           !_XftStrCmpIgnoreCase (cf->xlfd, xlfd))
2971 +       {
2972 +           cf->ref++;
2973 +           if (_XftFontDebug () & XFT_DBG_REF)
2974 +           {
2975 +               printf ("Xlfd \"%s\" matches existing font (%d)\n",
2976 +                       xlfd, cf->ref);
2977 +           }
2978 +           break;
2979 +       }
2980 +    }
2981 +    if (!cf)
2982 +    {
2983 +       ret = XLoadQueryFont (dpy, xlfd);
2984 +       if (!ret)
2985 +           return 0;
2986 +
2987 +       cf = (XftCoreFont *) malloc (sizeof (XftCoreFont) +
2988 +                                    strlen (xlfd) + 1);
2989 +       if (!cf)
2990 +       {
2991 +           XFreeFont (dpy, ret);
2992 +           return 0;
2993 +       }
2994 +       
2995 +        if (_XftFontDebug () & XFT_DBG_REF)
2996 +           printf ("Xlfd \"%s\" matches new font\n", xlfd);
2997 +       
2998 +       cf->next = _XftCoreFonts;
2999 +       _XftCoreFonts = cf;
3000 +       cf->ref = 1;
3001 +       
3002 +       cf->font = ret;
3003 +       cf->xlfd = (char *) (cf + 1);
3004 +       strcpy (cf->xlfd, xlfd);
3005 +    }
3006      if (xlfd_pixel)
3007         free (xlfd_pixel);
3008 -    return ret;
3009 +    return cf->font;
3010  }
3011  
3012 +void
3013 +XftCoreClose (Display *dpy, XFontStruct *font)
3014 +{
3015 +    XftCoreFont        *cf, **prev;
3016 +
3017 +    for (prev = &_XftCoreFonts; (cf = *prev); prev = &cf->next)
3018 +    {
3019 +       if (cf->display == dpy && cf->font == font)
3020 +       {
3021 +           if (--cf->ref == 0)
3022 +           {
3023 +               XFreeFont (dpy, cf->font);
3024 +               *prev = cf->next;
3025 +               free (cf);
3026 +           }
3027 +           break;
3028 +       }
3029 +    }
3030 +}
This page took 0.506802 seconds and 3 git commands to generate.