]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fontfile/fontdir.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / fontfile / fontdir.c
1 /* $XConsortium: fontdir.c /main/24 1996/09/28 16:49:04 rws $ */
2 /* $XFree86: xc/lib/font/fontfile/fontdir.c,v 3.7 1996/12/23 06:02:21 dawes Exp $ */
3
4 /*
5
6 Copyright (c) 1991  X Consortium
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the name of the X Consortium shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings
27 in this Software without prior written authorization from the X Consortium.
28
29 */
30
31 /*
32  * Author:  Keith Packard, MIT X Consortium
33  */
34
35 #include    "fntfilst.h"
36 #include    <X11/keysym.h>
37
38 Bool
39 FontFileInitTable (table, size)
40     FontTablePtr    table;
41     int             size;
42 {
43     if (size)
44     {
45         table->entries = (FontEntryPtr) xalloc(sizeof(FontEntryRec) * size);
46         if (!table->entries)
47             return FALSE;
48     }
49     else
50         table->entries = 0;
51     table->used = 0;
52     table->size = size;
53     table->sorted = FALSE;
54     return TRUE;
55 }
56
57 FontFileFreeEntry (entry)
58     FontEntryPtr    entry;
59 {
60     FontScalableExtraPtr   extra;
61     int i;
62
63     if (entry->name.name)
64         xfree(entry->name.name);
65
66     switch (entry->type)
67     {
68     case FONT_ENTRY_SCALABLE:
69         xfree (entry->u.scalable.fileName);
70         extra = entry->u.scalable.extra;
71         for (i = 0; i < extra->numScaled; i++)
72             if (extra->scaled[i].vals.ranges)
73                 xfree (extra->scaled[i].vals.ranges);
74         xfree (extra->scaled);
75         xfree (extra);
76         break;
77     case FONT_ENTRY_BITMAP:
78         xfree (entry->u.bitmap.fileName);
79         break;
80     case FONT_ENTRY_ALIAS:
81         xfree (entry->u.alias.resolved);
82         break;
83 #ifdef NOTYET
84     case FONT_ENTRY_BC:
85         break;
86 #endif
87     }
88 }
89
90 FontFileFreeTable (table)
91     FontTablePtr    table;
92 {
93     int i;
94
95     for (i = 0; i < table->used; i++)
96         FontFileFreeEntry (&table->entries[i]);
97     xfree (table->entries);
98 }
99
100 FontDirectoryPtr
101 FontFileMakeDir(dirName, size)
102     char       *dirName;
103     int         size;
104 {
105     FontDirectoryPtr    dir;
106     int                 dirlen;
107     int                 needslash = 0;
108 #ifdef FONTDIRATTRIB
109     char                *attrib;
110     int                 attriblen;
111 #endif
112
113 #ifdef FONTDIRATTRIB
114 #ifndef __EMX__
115     attrib = strchr(dirName, ':');
116 #else
117     /* OS/2 uses the colon in the drive letter descriptor, skip this */
118     attrib = strchr(dirName+2, ':');
119 #endif
120     if (attrib) {
121         dirlen = attrib - dirName;
122         attriblen = strlen(attrib);
123     } else {
124         dirlen = strlen(dirName);
125         attriblen = 0;
126     }
127 #else
128     dirlen = strlen(dirName);
129 #endif
130     if (dirName[dirlen - 1] != '/')
131 #ifdef NCD
132     if (dirlen)     /* leave out slash for builtins */
133 #endif
134         needslash = 1;
135 #ifdef FONTDIRATTRIB
136     dir = (FontDirectoryPtr) xalloc(sizeof *dir + dirlen + needslash + 1 +
137                                     (attriblen ? attriblen + 1 : 0));
138 #else
139     dir = (FontDirectoryPtr) xalloc(sizeof *dir + dirlen + needslash + 1);
140 #endif
141     if (!dir)
142         return (FontDirectoryPtr)0;
143     if (!FontFileInitTable (&dir->scalable, 0))
144     {
145         xfree (dir);
146         return (FontDirectoryPtr)0;
147     }
148     if (!FontFileInitTable (&dir->nonScalable, size))
149     {
150         FontFileFreeTable (&dir->scalable);
151         xfree (dir);
152         return (FontDirectoryPtr)0;
153     }
154     dir->directory = (char *) (dir + 1);
155     dir->dir_mtime = 0;
156     dir->alias_mtime = 0;
157 #ifdef FONTDIRATTRIB
158     if (attriblen)
159         dir->attributes = dir->directory + dirlen + needslash + 1;
160     else
161         dir->attributes = NULL;
162     strncpy(dir->directory, dirName, dirlen);
163     dir->directory[dirlen] = '\0';
164     if (dir->attributes)
165         strcpy(dir->attributes, attrib);
166 #else
167     strcpy(dir->directory, dirName);
168 #endif
169     if (needslash)
170         strcat(dir->directory, "/");
171     return dir;
172 }
173
174 FontFileFreeDir (dir)
175     FontDirectoryPtr    dir;
176 {
177     FontFileFreeTable (&dir->scalable);
178     FontFileFreeTable (&dir->nonScalable);
179     xfree(dir);
180 }
181
182 FontEntryPtr
183 FontFileAddEntry(table, prototype)
184     FontTablePtr        table;
185     FontEntryPtr        prototype;
186 {
187     FontEntryPtr    entry;
188     int             newsize;
189
190     /* can't add entries to a sorted table, pointers get broken! */
191     if (table->sorted)
192         return (FontEntryPtr) 0;    /* "cannot" happen */
193     if (table->used == table->size) {
194         newsize = table->size + 100;
195         entry = (FontEntryPtr) xrealloc(table->entries,
196                                            newsize * sizeof(FontEntryRec));
197         if (!entry)
198             return (FontEntryPtr)0;
199         table->size = newsize;
200         table->entries = entry;
201     }
202     entry = &table->entries[table->used];
203     *entry = *prototype;
204     entry->name.name = (char *) xalloc(prototype->name.length + 1);
205     if (!entry->name.name)
206         return (FontEntryPtr)0;
207     memcpy (entry->name.name, prototype->name.name, prototype->name.length);
208     entry->name.name[entry->name.length] = '\0';
209     table->used++;
210     return entry;
211 }
212
213 static int
214 FontFileNameCompare(a, b)
215     char       *a,
216                *b;
217 {
218     FontEntryPtr    a_name = (FontEntryPtr) a,
219                     b_name = (FontEntryPtr) b;
220
221     return strcmp(a_name->name.name, b_name->name.name);
222 }
223
224 FontFileSortTable (table)
225     FontTablePtr    table;
226 {
227     if (!table->sorted) {
228         qsort((char *) table->entries, table->used, sizeof(FontEntryRec),
229               FontFileNameCompare);
230         table->sorted = TRUE;
231     }
232 }
233
234 FontFileSortDir(dir)
235     FontDirectoryPtr    dir;
236 {
237     FontFileSortTable (&dir->scalable);
238     FontFileSortTable (&dir->nonScalable);
239     /* now that the table is fixed in size, swizzle the pointers */
240     FontFileSwitchStringsToBitmapPointers (dir);
241 }
242
243 /*
244   Given a Font Table, SetupWildMatch() sets up various pointers and state
245   information so the table can be searched for name(s) that match a given
246   fontname pattern -- which may contain wildcards.  Under certain
247   circumstances, SetupWildMatch() will find the one table entry that
248   matches the pattern.  If those circumstances do not pertain,
249   SetupWildMatch() returns a range within the the table that should be
250   searched for matching name(s).  With the information established by
251   SetupWildMatch(), including state information in "private", the
252   PatternMatch() procedure is then used to test names in the range for a
253   match.
254 */
255
256 #define isWild(c)   ((c) == XK_asterisk || (c) == XK_question)
257
258 static int
259 SetupWildMatch(table, pat, leftp, rightp, privatep)
260     FontTablePtr    table;
261     FontNamePtr     pat;
262     int             *leftp,
263                     *rightp;
264     int             *privatep;
265 {
266     int         nDashes;
267     char        c;
268     char       *t;
269     char       *firstWild;
270     int         first;
271     int         center,
272                 left,
273                 right;
274     int         result;
275     char        *name;
276
277     name = pat->name;
278     nDashes = pat->ndashes;
279     firstWild = 0;
280     t = name;
281     while (c = *t++) {
282         if (isWild(c)) {
283             if (!firstWild)
284                 firstWild = t - 1;
285         }
286     }
287     left = 0;
288     right = table->used;
289     if (firstWild)
290         *privatep = nDashes;
291     else
292         *privatep = -1;
293     if (!table->sorted) {
294         *leftp = left;
295         *rightp = right;
296         return -1;
297     } else if (firstWild) {
298         first = firstWild - name;
299         while (left < right) {
300             center = (left + right) / 2;
301             result = strncmp(name, table->entries[center].name.name, first);
302             if (result == 0)
303                 break;
304             if (result < 0)
305                 right = center;
306             else
307                 left = center + 1;
308         }
309         *leftp = left;
310         *rightp = right;
311         return -1;
312     } else {
313         while (left < right) {
314             center = (left + right) / 2;
315             result = strcmp(name, table->entries[center].name.name);
316             if (result == 0)
317                 return center;
318             if (result < 0)
319                 right = center;
320             else
321                 left = center + 1;
322         }
323         *leftp = 1;
324         *rightp = 0;
325         return -1;
326     }
327 }
328
329 static
330 PatternMatch(pat, patdashes, string, stringdashes)
331     char       *pat;
332     char       *string;
333 {
334     char        c,
335                 t;
336
337     if (stringdashes < patdashes)
338         return 0;
339     for (;;) {
340         switch (c = *pat++) {
341         case '*':
342             if (!(c = *pat++))
343                 return 1;
344             if (c == XK_minus) {
345                 patdashes--;
346                 for (;;) {
347                     while ((t = *string++) != XK_minus)
348                         if (!t)
349                             return 0;
350                     stringdashes--;
351                     if (PatternMatch(pat, patdashes, string, stringdashes))
352                         return 1;
353                     if (stringdashes == patdashes)
354                         return 0;
355                 }
356             } else {
357                 for (;;) {
358                     while ((t = *string++) != c) {
359                         if (!t)
360                             return 0;
361                         if (t == XK_minus) {
362                             if (stringdashes-- < patdashes)
363                                 return 0;
364                         }
365                     }
366                     if (PatternMatch(pat, patdashes, string, stringdashes))
367                         return 1;
368                 }
369             }
370         case '?':
371             if (*string++ == XK_minus)
372                 stringdashes--;
373             break;
374         case '\0':
375             return (*string == '\0');
376         case XK_minus:
377             if (*string++ == XK_minus) {
378                 patdashes--;
379                 stringdashes--;
380                 break;
381             }
382             return 0;
383         default:
384             if (c == *string++)
385                 break;
386             return 0;
387         }
388     }
389 }
390
391 int
392 FontFileCountDashes (name, namelen)
393     char    *name;
394     int     namelen;
395 {
396     int ndashes = 0;
397
398     while (namelen--)
399         if (*name++ == '\055')  /* avoid non ascii systems */
400             ++ndashes;
401     return ndashes;
402 }
403
404 char *
405 FontFileSaveString (s)
406     char    *s;
407 {
408     char    *n;
409
410     n = (char *) xalloc (strlen (s) + 1);
411     if (!n)
412         return 0;
413     strcpy (n, s);
414     return n;
415 }
416
417 FontEntryPtr
418 FontFileFindNameInScalableDir(table, pat, vals)
419     FontTablePtr    table;
420     FontNamePtr     pat;
421     FontScalablePtr     vals;
422 {
423     int         i,
424                 start,
425                 stop,
426                 res,
427                 private;
428     FontNamePtr name;
429
430     if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0)
431         return &table->entries[i];
432     for (i = start; i < stop; i++) {
433         name = &table->entries[i].name;
434         res = PatternMatch(pat->name, private, name->name, name->ndashes);
435         if (res > 0)
436         {
437             /* Check to see if enhancements requested are available */
438             if (vals)
439             {
440                 int vs = vals->values_supplied;
441                 int cap;
442
443                 if (table->entries[i].type == FONT_ENTRY_SCALABLE)
444                     cap = table->entries[i].u.scalable.renderer->capabilities;
445                 else if (table->entries[i].type == FONT_ENTRY_ALIAS)
446                     cap = ~0;   /* Calling code will have to see if true */
447                 else
448                     cap = 0;
449                 if (((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
450                      (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
451                     !(cap & CAP_MATRIX) ||
452                     (vs & CHARSUBSET_SPECIFIED) &&
453                     !(cap & CAP_CHARSUBSETTING))
454                     continue;
455             }
456             return &table->entries[i];
457         }
458         if (res < 0)
459             break;
460     }
461     return (FontEntryPtr)0;
462 }
463
464 FontEntryPtr
465 FontFileFindNameInDir(table, pat)
466     FontTablePtr    table;
467     FontNamePtr     pat;
468 {
469     return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0);
470 }
471
472 FontFileFindNamesInScalableDir(table, pat, max, names, vals,
473                                alias_behavior, newmax)
474     FontTablePtr    table;
475     FontNamePtr     pat;
476     int             max;
477     FontNamesPtr    names;
478     FontScalablePtr     vals;
479     int             alias_behavior;
480     int            *newmax;
481 {
482     int             i,
483                     start,
484                     stop,
485                     res,
486                     private;
487     int             ret = Successful;
488     FontEntryPtr    fname;
489     FontNamePtr     name;
490
491     if (max <= 0)
492         return Successful;
493     if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) {
494         if (alias_behavior == NORMAL_ALIAS_BEHAVIOR ||
495             table->entries[i].type != FONT_ENTRY_ALIAS)
496         {
497             name = &table->entries[i].name;
498             if (newmax) *newmax = max - 1;
499             return AddFontNamesName(names, name->name, name->length);
500         }
501         start = i;
502         stop = i + 1;
503     }
504     for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) {
505         res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes);
506         if (res > 0) {
507             if (vals)
508             {
509                 int vs = vals->values_supplied;
510                 int cap;
511
512                 if (fname->type == FONT_ENTRY_SCALABLE)
513                     cap = fname->u.scalable.renderer->capabilities;
514                 else if (fname->type == FONT_ENTRY_ALIAS)
515                     cap = ~0;   /* Calling code will have to see if true */
516                 else
517                     cap = 0;
518                 if (((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
519                      (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
520                     !(cap & CAP_MATRIX) ||
521                     (vs & CHARSUBSET_SPECIFIED) &&
522                     !(cap & CAP_CHARSUBSETTING))
523                     continue;
524             }
525
526             if ((alias_behavior & IGNORE_SCALABLE_ALIASES) &&
527                 fname->type == FONT_ENTRY_ALIAS)
528             {
529                 FontScalableRec tmpvals;
530                 if (FontParseXLFDName (fname->name.name, &tmpvals,
531                                        FONT_XLFD_REPLACE_NONE) &&
532                     !(tmpvals.values_supplied & SIZE_SPECIFY_MASK))
533                     continue;
534             }
535
536             ret = AddFontNamesName(names, fname->name.name, fname->name.length);
537             if (ret != Successful)
538                 goto bail;
539
540             /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark
541                this entry as an alias by negating its length and follow
542                it by the resolved name */
543             if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) &&
544                 fname->type == FONT_ENTRY_ALIAS)
545             {
546                 names->length[names->nnames - 1] =
547                     -names->length[names->nnames - 1];
548                 ret = AddFontNamesName(names, fname->u.alias.resolved,
549                                        strlen(fname->u.alias.resolved));
550                 if (ret != Successful)
551                     goto bail;
552             }
553
554             if (--max <= 0)
555                 break;
556         } else if (res < 0)
557             break;
558     }
559   bail: ;
560     if (newmax) *newmax = max;
561     return ret;
562 }
563
564 int
565 FontFileFindNamesInDir(table, pat, max, names)
566     FontTablePtr    table;
567     FontNamePtr     pat;
568     int             max;
569     FontNamesPtr    names;
570 {
571     return FontFileFindNamesInScalableDir(table, pat, max, names,
572                                           (FontScalablePtr)0,
573                                           NORMAL_ALIAS_BEHAVIOR, (int *)0);
574 }
575
576 Bool
577 FontFileMatchName(name, length, pat)
578     char        *name;
579     int         length;
580     FontNamePtr pat;
581 {
582     /* Perform a fontfile-type name match on a single name */
583     FontTableRec table;
584     FontEntryRec entries[1];
585
586     /* Dummy up a table */
587     table.used = 1;
588     table.size = 1;
589     table.sorted = TRUE;
590     table.entries = entries;
591     entries[0].name.name = name;
592     entries[0].name.length = length;
593     entries[0].name.ndashes = FontFileCountDashes(name, length);
594
595     return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0;
596 }
597
598 /*
599  * Add a font file to a directory.  This handles bitmap and
600  * scalable names both
601  */
602
603 Bool
604 FontFileAddFontFile (dir, fontName, fileName)
605     FontDirectoryPtr    dir;
606     char                *fontName;
607     char                *fileName;
608 {
609     FontEntryRec            entry;
610     FontScalableRec         vals, zeroVals;
611     FontRendererPtr         renderer;
612     FontEntryPtr            existing;
613     FontScalableExtraPtr    extra;
614     FontEntryPtr            bitmap, scalable;
615     Bool                    isscale;
616
617     renderer = FontFileMatchRenderer (fileName);
618     if (!renderer)
619         return FALSE;
620     entry.name.length = strlen (fontName);
621     if (entry.name.length > MAXFONTNAMELEN)
622         entry.name.length = MAXFONTNAMELEN;
623     entry.name.name = fontName;
624     CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length);
625     entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
626     entry.name.name[entry.name.length] = '\0';
627     /*
628      * Add a bitmap name if the incoming name isn't an XLFD name, or
629      * if it isn't a scalable name (i.e. non-zero scalable fields)
630      *
631      * If name of bitmapped font contains XLFD enhancements, do not add
632      * a scalable version of the name... this can lead to confusion and
633      * ambiguity between the font name and the field enhancements.
634      */
635     isscale = entry.name.ndashes == 14 &&
636               FontParseXLFDName(entry.name.name,
637                                 &vals, FONT_XLFD_REPLACE_NONE) &&
638               (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY &&
639               (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY &&
640               !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK);
641 #ifdef FONTDIRATTRIB
642 #define UNSCALED_ATTRIB "unscaled"
643     /* For scalable fonts, check if the "unscaled" attribute is present */
644     if (isscale && dir->attributes && dir->attributes[0] == ':') {
645         char *ptr1 = dir->attributes + 1;
646         char *ptr2;
647         int length;
648         int uslength = strlen(UNSCALED_ATTRIB);
649
650         do {
651             ptr2 = strchr(ptr1, ':');
652             if (ptr2)
653                 length = ptr2 - ptr1;
654             else
655                 length = dir->attributes + strlen(dir->attributes) - ptr1;
656             if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength))
657                 isscale = FALSE;
658             if (ptr2)
659                 ptr1 = ptr2 + 1;
660         } while (ptr2);
661     }
662 #endif
663     if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK))
664     {
665       /* If the fontname says it is nonScalable, make sure that the
666        * renderer supports OpenBitmap and GetInfoBitmap.
667        */
668       if (renderer->OpenBitmap && renderer->GetInfoBitmap)
669       {
670         entry.type = FONT_ENTRY_BITMAP;
671         entry.u.bitmap.renderer = renderer;
672         entry.u.bitmap.pFont = NullFont;
673         if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName)))
674             return FALSE;
675         if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry)))
676         {
677             xfree (entry.u.bitmap.fileName);
678             return FALSE;
679         }
680       }
681     }
682     /*
683      * Parse out scalable fields from XLFD names - a scalable name
684      * just gets inserted, a scaled name has more things to do.
685      */
686     if (isscale)
687     {
688       /* If the fontname says it is scalable, make sure that the
689        * renderer supports OpenScalable and GetInfoScalable.
690        */
691       if (renderer->OpenScalable && renderer->GetInfoScalable)
692       {
693         if (vals.values_supplied & SIZE_SPECIFY_MASK)
694         {
695             bzero((char *)&zeroVals, sizeof(zeroVals));
696             zeroVals.x = vals.x;
697             zeroVals.y = vals.y;
698             zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR;
699             FontParseXLFDName (entry.name.name, &zeroVals,
700                                FONT_XLFD_REPLACE_VALUE);
701             entry.name.length = strlen (entry.name.name);
702             existing = FontFileFindNameInDir (&dir->scalable, &entry.name);
703             if (existing)
704             {
705                 if ((vals.values_supplied & POINTSIZE_MASK) ==
706                         POINTSIZE_SCALAR &&
707                     (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
708                 {
709                     existing->u.scalable.extra->defaults = vals;
710
711                     xfree (existing->u.scalable.fileName);
712                     if (!(existing->u.scalable.fileName = FontFileSaveString (fileName)))
713                         return FALSE;
714                 }
715                 FontFileCompleteXLFD(&vals, &vals);
716                 FontFileAddScaledInstance (existing, &vals, NullFont,
717                                            bitmap->name.name);
718                 return TRUE;
719             }
720         }
721         if (!(entry.u.scalable.fileName = FontFileSaveString (fileName)))
722             return FALSE;
723         extra = (FontScalableExtraPtr) xalloc (sizeof (FontScalableExtraRec));
724         if (!extra)
725         {
726             xfree (entry.u.scalable.fileName);
727             return FALSE;
728         }
729         bzero((char *)&extra->defaults, sizeof(extra->defaults));
730         if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR &&
731             (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
732             extra->defaults = vals;
733         else
734         {
735             FontResolutionPtr resolution;
736             int num;
737
738             extra->defaults.point_matrix[0] =
739                 extra->defaults.point_matrix[3] =
740                     (double)GetDefaultPointSize() / 10.0;
741             extra->defaults.point_matrix[1] =
742                 extra->defaults.point_matrix[2] = 0.0;
743             extra->defaults.values_supplied =
744                 POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED;
745             extra->defaults.width = -1;
746             if (vals.x <= 0 || vals.y <= 0)
747             {
748                 resolution = GetClientResolutions (&num);
749                 if (resolution && num > 0)
750                 {
751                     extra->defaults.x = resolution->x_resolution;
752                     extra->defaults.y = resolution->y_resolution;
753                 }
754                 else
755                 {
756                     extra->defaults.x = 75;
757                     extra->defaults.y = 75;
758                 }
759              }
760              else 
761              {
762                 extra->defaults.x = vals.x;
763                 extra->defaults.y = vals.y;
764              }
765              FontFileCompleteXLFD (&extra->defaults, &extra->defaults);
766         }
767         extra->numScaled = 0;
768         extra->sizeScaled = 0;
769         extra->scaled = 0;
770         extra->private = 0;
771         entry.type = FONT_ENTRY_SCALABLE;
772         entry.u.scalable.renderer = renderer;
773         entry.u.scalable.extra = extra;
774         if (!(scalable = FontFileAddEntry (&dir->scalable, &entry)))
775         {
776             xfree (extra);
777             xfree (entry.u.scalable.fileName);
778             return FALSE;
779         }
780         if (vals.values_supplied & SIZE_SPECIFY_MASK)
781         {
782             FontFileCompleteXLFD(&vals, &vals);
783             FontFileAddScaledInstance (scalable, &vals, NullFont,
784                                        bitmap->name.name);
785         }
786       }
787     }
788     return TRUE;
789 }
790
791 Bool
792 FontFileAddFontAlias (dir, aliasName, fontName)
793     FontDirectoryPtr    dir;
794     char                *aliasName;
795     char                *fontName;
796 {
797     FontEntryRec        entry;
798
799     entry.name.length = strlen (aliasName);
800     CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length);
801     entry.name.name = aliasName;
802     entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
803     entry.type = FONT_ENTRY_ALIAS;
804     if (!(entry.u.alias.resolved = FontFileSaveString (fontName)))
805         return FALSE;
806     if (!FontFileAddEntry (&dir->nonScalable, &entry))
807     {
808         xfree (entry.u.alias.resolved);
809         return FALSE;
810     }
811     return TRUE;
812 }