1/* 2 3Copyright 1991, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in 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 45Bool 46FontFileInitTable (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 64void 65FontFileFreeEntry (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 96void 97FontFileFreeTable (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 106FontDirectoryPtr 107FontFileMakeDir(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 attrib = strchr(dirName, ':'); 116#if defined(WIN32) 117 if (attrib && attrib - dirName == 1) { 118 /* WIN32 uses the colon in the drive letter descriptor, skip this */ 119 attrib = strchr(dirName + 2, ':'); 120 } 121#endif 122 if (attrib) { 123 dirlen = attrib - dirName; 124 attriblen = strlen(attrib); 125 } else { 126 dirlen = strlen(dirName); 127 attriblen = 0; 128 } 129 if (dirlen && dirName[dirlen - 1] != '/') 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 if (needslash) 155 dir->directory[dirlen] = '/'; 156 dir->directory[dirlen + needslash] = '\0'; 157 if (dir->attributes) 158 strlcpy(dir->attributes, attrib, attriblen + 1); 159 return dir; 160} 161 162void 163FontFileFreeDir (FontDirectoryPtr dir) 164{ 165 FontFileFreeTable (&dir->scalable); 166 FontFileFreeTable (&dir->nonScalable); 167 free(dir); 168} 169 170FontEntryPtr 171FontFileAddEntry(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 = reallocarray(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 213static 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 242static int 243FontFileNameCompare(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 251void 252FontFileSortTable (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 261void 262FontFileSortDir(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 286static int 287SetupWildMatch(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 362static int 363PatternMatch(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 424int 425FontFileCountDashes (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> */ 436char * 437FontFileSaveString (char *s) 438{ 439 return strdup(s); 440} 441#define FontFileSaveString(s) strdup(s) 442 443FontEntryPtr 444FontFileFindNameInScalableDir(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 490FontEntryPtr 491FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat) 492{ 493 return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0); 494} 495 496int 497FontFileFindNamesInScalableDir(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 xfont2_add_font_names_name(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 = xfont2_add_font_names_name(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 = xfont2_add_font_names_name(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 583int 584FontFileFindNamesInDir(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 592Bool 593FontFileMatchName(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 616Bool 617FontFileAddFontFile (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 806Bool 807FontFileAddFontAlias (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