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