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