fontfile.c revision 0145ab54
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 <X11/fonts/fntfilst.h> 35#include <X11/keysym.h> 36#ifdef WIN32 37#include <ctype.h> 38#endif 39 40static unsigned char 41ISOLatin1ToLower(unsigned char source) 42{ 43 if (source >= XK_A && source <= XK_Z) 44 return source + (XK_a - XK_A); 45 if (source >= XK_Agrave && source <= XK_Odiaeresis) 46 return source + (XK_agrave - XK_Agrave); 47 if (source >= XK_Ooblique && source <= XK_Thorn) 48 return source + (XK_oslash - XK_Ooblique); 49 return source; 50} 51 52_X_HIDDEN void 53CopyISOLatin1Lowered(char *dest, const char *source, int length) 54{ 55 int i; 56 for (i = 0; i < length; i++, source++, dest++) 57 *dest = ISOLatin1ToLower(*source); 58 *dest = '\0'; 59} 60 61/* 62 * Map FPE functions to renderer functions 63 */ 64 65static int FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, 66 int flags, FontEntryPtr entry, 67 fsBitmapFormat format, 68 fsBitmapFormatMask fmask, 69 FontPtr non_cachable_font); 70 71int 72FontFileNameCheck (const char *name) 73{ 74#ifndef NCD 75#if defined(WIN32) 76 /* OS/2 uses D:/... as a path name for fonts, so accept this as a valid 77 * path if it starts with a letter and a colon. Same applies for WIN32 78 */ 79 if (isalpha(*name) && name[1]==':') 80 return TRUE; 81#endif 82 return *name == '/'; 83#else 84 return ((strcmp(name, "built-ins") == 0) || (*name == '/')); 85#endif 86} 87 88int 89FontFileInitFPE (FontPathElementPtr fpe) 90{ 91 int status; 92 FontDirectoryPtr dir; 93 94 status = FontFileReadDirectory (fpe->name, &dir); 95 if (status == Successful) 96 { 97 if (dir->nonScalable.used > 0) 98 if (!FontFileRegisterBitmapSource (fpe)) 99 { 100 FontFileFreeFPE (fpe); 101 return AllocError; 102 } 103 fpe->private = (pointer) dir; 104 } 105 return status; 106} 107 108/* ARGSUSED */ 109int 110FontFileResetFPE (FontPathElementPtr fpe) 111{ 112 FontDirectoryPtr dir; 113 114 dir = (FontDirectoryPtr) fpe->private; 115 /* 116 * The reset must fail for bitmap fonts because they get cleared when 117 * the path is set. 118 */ 119 if (FontFileDirectoryChanged (dir)) 120 { 121 /* can't do it, so tell the caller to close and re-open */ 122 return FPEResetFailed; 123 } 124 else 125 { 126 if (dir->nonScalable.used > 0) 127 if (!FontFileRegisterBitmapSource (fpe)) 128 { 129 return FPEResetFailed; 130 } 131 return Successful; 132 } 133} 134 135int 136FontFileFreeFPE (FontPathElementPtr fpe) 137{ 138 FontFileUnregisterBitmapSource (fpe); 139 FontFileFreeDir ((FontDirectoryPtr) fpe->private); 140 return Successful; 141} 142 143static int 144transfer_values_to_alias(char *entryname, int entrynamelength, 145 char *resolvedname, 146 char **aliasName, FontScalablePtr vals) 147{ 148 static char aliasname[MAXFONTNAMELEN]; 149 int nameok = 1, len; 150 char lowerName[MAXFONTNAMELEN]; 151 152 *aliasName = resolvedname; 153 if ((len = strlen(*aliasName)) <= MAXFONTNAMELEN && 154 (entrynamelength < MAXFONTNAMELEN) && 155 FontFileCountDashes (*aliasName, len) == 14) 156 { 157 FontScalableRec tmpVals; 158 FontScalableRec tmpVals2; 159 160 tmpVals2 = *vals; 161 162 /* If we're aliasing a scalable name, transfer values 163 from the name into the destination alias, multiplying 164 by matrices that appear in the alias. */ 165 166 CopyISOLatin1Lowered (lowerName, entryname, 167 entrynamelength); 168 lowerName[entrynamelength] = '\0'; 169 170 if (FontParseXLFDName(lowerName, &tmpVals, 171 FONT_XLFD_REPLACE_NONE) && 172 !tmpVals.values_supplied && 173 FontParseXLFDName(*aliasName, &tmpVals, 174 FONT_XLFD_REPLACE_NONE)) 175 { 176 double *matrix = 0, tempmatrix[4]; 177 178 /* Use a matrix iff exactly one is defined */ 179 if ((tmpVals.values_supplied & PIXELSIZE_MASK) == 180 PIXELSIZE_ARRAY && 181 !(tmpVals.values_supplied & POINTSIZE_MASK)) 182 matrix = tmpVals.pixel_matrix; 183 else if ((tmpVals.values_supplied & POINTSIZE_MASK) == 184 POINTSIZE_ARRAY && 185 !(tmpVals.values_supplied & PIXELSIZE_MASK)) 186 matrix = tmpVals.point_matrix; 187 188 /* If matrix given in the alias, compute new point 189 and/or pixel matrices */ 190 if (matrix) 191 { 192 /* Complete the XLFD name to avoid potential 193 gotchas */ 194 if (FontFileCompleteXLFD(&tmpVals2, &tmpVals2)) 195 { 196 tempmatrix[0] = 197 matrix[0] * tmpVals2.point_matrix[0] + 198 matrix[1] * tmpVals2.point_matrix[2]; 199 tempmatrix[1] = 200 matrix[0] * tmpVals2.point_matrix[1] + 201 matrix[1] * tmpVals2.point_matrix[3]; 202 tempmatrix[2] = 203 matrix[2] * tmpVals2.point_matrix[0] + 204 matrix[3] * tmpVals2.point_matrix[2]; 205 tempmatrix[3] = 206 matrix[2] * tmpVals2.point_matrix[1] + 207 matrix[3] * tmpVals2.point_matrix[3]; 208 tmpVals2.point_matrix[0] = tempmatrix[0]; 209 tmpVals2.point_matrix[1] = tempmatrix[1]; 210 tmpVals2.point_matrix[2] = tempmatrix[2]; 211 tmpVals2.point_matrix[3] = tempmatrix[3]; 212 213 tempmatrix[0] = 214 matrix[0] * tmpVals2.pixel_matrix[0] + 215 matrix[1] * tmpVals2.pixel_matrix[2]; 216 tempmatrix[1] = 217 matrix[0] * tmpVals2.pixel_matrix[1] + 218 matrix[1] * tmpVals2.pixel_matrix[3]; 219 tempmatrix[2] = 220 matrix[2] * tmpVals2.pixel_matrix[0] + 221 matrix[3] * tmpVals2.pixel_matrix[2]; 222 tempmatrix[3] = 223 matrix[2] * tmpVals2.pixel_matrix[1] + 224 matrix[3] * tmpVals2.pixel_matrix[3]; 225 tmpVals2.pixel_matrix[0] = tempmatrix[0]; 226 tmpVals2.pixel_matrix[1] = tempmatrix[1]; 227 tmpVals2.pixel_matrix[2] = tempmatrix[2]; 228 tmpVals2.pixel_matrix[3] = tempmatrix[3]; 229 230 tmpVals2.values_supplied = 231 (tmpVals2.values_supplied & 232 ~(PIXELSIZE_MASK | POINTSIZE_MASK)) | 233 PIXELSIZE_ARRAY | POINTSIZE_ARRAY; 234 } 235 else 236 nameok = 0; 237 } 238 239 CopyISOLatin1Lowered (aliasname, *aliasName, len + 1); 240 if (nameok && FontParseXLFDName(aliasname, &tmpVals2, 241 FONT_XLFD_REPLACE_VALUE)) 242 /* Return a version of the aliasname that has 243 had the vals stuffed into it. To avoid 244 memory leak, this alias name lives in a 245 static buffer. The caller needs to be done 246 with this buffer before this procedure is 247 called again to avoid reentrancy problems. */ 248 *aliasName = aliasname; 249 } 250 } 251 return nameok; 252} 253 254/* ARGSUSED */ 255int 256FontFileOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, 257 const char *name, int namelen, 258 fsBitmapFormat format, fsBitmapFormatMask fmask, 259 XID id, FontPtr *pFont, char **aliasName, 260 FontPtr non_cachable_font) 261{ 262 FontDirectoryPtr dir; 263 char lowerName[MAXFONTNAMELEN]; 264 char fileName[MAXFONTFILENAMELEN*2 + 1]; 265 FontNameRec tmpName; 266 FontEntryPtr entry; 267 FontScalableRec vals; 268 FontScalableEntryPtr scalable; 269 FontScaledPtr scaled; 270 FontBitmapEntryPtr bitmap; 271 int ret; 272 Bool noSpecificSize; 273 int nranges; 274 fsRange *ranges; 275 276 if (namelen >= MAXFONTNAMELEN) 277 return AllocError; 278 dir = (FontDirectoryPtr) fpe->private; 279 280 /* Match non-scalable pattern */ 281 CopyISOLatin1Lowered (lowerName, name, namelen); 282 lowerName[namelen] = '\0'; 283 ranges = FontParseRanges(lowerName, &nranges); 284 tmpName.name = lowerName; 285 tmpName.length = namelen; 286 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 287 if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) 288 bzero(&vals, sizeof(vals)); 289 if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && 290 tmpName.ndashes == 14 && 291 FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) 292 { 293 tmpName.length = strlen(lowerName); 294 entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); 295 } 296 297 if (entry) 298 { 299 switch (entry->type) { 300 case FONT_ENTRY_BITMAP: 301 bitmap = &entry->u.bitmap; 302 if (bitmap->pFont) 303 { 304 *pFont = bitmap->pFont; 305 (*pFont)->fpe = fpe; 306 ret = Successful; 307 } 308 else 309 { 310 ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, 311 fmask, non_cachable_font); 312 if (ret == Successful && *pFont) 313 (*pFont)->fpe = fpe; 314 } 315 break; 316 case FONT_ENTRY_ALIAS: 317 vals.nranges = nranges; 318 vals.ranges = ranges; 319 transfer_values_to_alias(entry->name.name, entry->name.length, 320 entry->u.alias.resolved, aliasName, &vals); 321 ret = FontNameAlias; 322 break; 323 default: 324 ret = BadFontName; 325 } 326 } 327 else 328 { 329 ret = BadFontName; 330 } 331 332 if (ret != BadFontName) 333 { 334 if (ranges) free(ranges); 335 return ret; 336 } 337 338 /* Match XLFD patterns */ 339 CopyISOLatin1Lowered (lowerName, name, namelen); 340 lowerName[namelen] = '\0'; 341 tmpName.name = lowerName; 342 tmpName.length = namelen; 343 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 344 if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || 345 !(tmpName.length = strlen (lowerName), 346 entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, 347 &vals))) { 348 CopyISOLatin1Lowered (lowerName, name, namelen); 349 lowerName[namelen] = '\0'; 350 tmpName.name = lowerName; 351 tmpName.length = namelen; 352 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 353 entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); 354 if (entry) 355 { 356 strcpy(lowerName, entry->name.name); 357 tmpName.name = lowerName; 358 tmpName.length = entry->name.length; 359 tmpName.ndashes = entry->name.ndashes; 360 } 361 } 362 363 if (entry) 364 { 365 noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ 366 if (entry->type == FONT_ENTRY_SCALABLE && 367 FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) 368 { 369 scalable = &entry->u.scalable; 370 if ((vals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || 371 (vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY || 372 (vals.values_supplied & 373 ~SIZE_SPECIFY_MASK & ~CHARSUBSET_SPECIFIED)) 374 scaled = 0; 375 else 376 scaled = FontFileFindScaledInstance (entry, &vals, 377 noSpecificSize); 378 /* 379 * A scaled instance can occur one of two ways: 380 * 381 * Either the font has been scaled to this 382 * size already, in which case scaled->pFont 383 * will point at that font. 384 * 385 * Or a bitmap instance in this size exists, 386 * which is handled as if we got a pattern 387 * matching the bitmap font name. 388 */ 389 if (scaled) 390 { 391 if (scaled->pFont) 392 { 393 *pFont = scaled->pFont; 394 (*pFont)->fpe = fpe; 395 ret = Successful; 396 } 397 else if (scaled->bitmap) 398 { 399 entry = scaled->bitmap; 400 bitmap = &entry->u.bitmap; 401 if (bitmap->pFont) 402 { 403 *pFont = bitmap->pFont; 404 (*pFont)->fpe = fpe; 405 ret = Successful; 406 } 407 else 408 { 409 ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, 410 format, fmask, 411 non_cachable_font); 412 if (ret == Successful && *pFont) 413 (*pFont)->fpe = fpe; 414 } 415 } 416 else /* "cannot" happen */ 417 { 418 ret = BadFontName; 419 } 420 } 421 else 422 { 423 ret = FontFileMatchBitmapSource (fpe, pFont, flags, entry, &tmpName, &vals, format, fmask, noSpecificSize); 424 if (ret != Successful) 425 { 426 char origName[MAXFONTNAMELEN]; 427 428 CopyISOLatin1Lowered (origName, name, namelen); 429 origName[namelen] = '\0'; 430 431 /* Pass the original XLFD name in the vals 432 structure; the rasterizer is free to examine it 433 for hidden meanings. This information will not 434 be saved in the scaled-instances table. */ 435 436 vals.xlfdName = origName; 437 vals.ranges = ranges; 438 vals.nranges = nranges; 439 440 if (strlen(dir->directory) + strlen(scalable->fileName) >= 441 sizeof(fileName)) { 442 ret = BadFontName; 443 } else { 444 strcpy (fileName, dir->directory); 445 strcat (fileName, scalable->fileName); 446 if (scalable->renderer->OpenScalable) { 447 ret = (*scalable->renderer->OpenScalable) (fpe, pFont, 448 flags, entry, fileName, &vals, format, fmask, 449 non_cachable_font); 450 } 451 else if (scalable->renderer->OpenBitmap) { 452 ret = (*scalable->renderer->OpenBitmap) (fpe, pFont, 453 flags, entry, fileName, format, fmask, 454 non_cachable_font); 455 } 456 } 457 458 /* In case rasterizer does something bad because of 459 charset subsetting... */ 460 if (ret == Successful && 461 ((*pFont)->info.firstCol > (*pFont)->info.lastCol || 462 (*pFont)->info.firstRow > (*pFont)->info.lastRow)) 463 { 464 (*(*pFont)->unload_font)(*pFont); 465 ret = BadFontName; 466 } 467 /* Save the instance */ 468 if (ret == Successful) 469 { 470 if (FontFileAddScaledInstance (entry, &vals, 471 *pFont, (char *) 0)) 472 ranges = 0; 473 else 474 (*pFont)->fpePrivate = (pointer) 0; 475 (*pFont)->fpe = fpe; 476 } 477 } 478 } 479 } 480 } 481 else 482 ret = BadFontName; 483 484 if (ranges) 485 free(ranges); 486 return ret; 487} 488 489/* ARGSUSED */ 490void 491FontFileCloseFont (FontPathElementPtr fpe, FontPtr pFont) 492{ 493 FontEntryPtr entry; 494 495 if ((entry = (FontEntryPtr) pFont->fpePrivate)) { 496 switch (entry->type) { 497 case FONT_ENTRY_SCALABLE: 498 FontFileRemoveScaledInstance (entry, pFont); 499 break; 500 case FONT_ENTRY_BITMAP: 501 entry->u.bitmap.pFont = 0; 502 break; 503 default: 504 /* "cannot" happen */ 505 break; 506 } 507 pFont->fpePrivate = 0; 508 } 509 (*pFont->unload_font) (pFont); 510} 511 512static int 513FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, 514 int flags, FontEntryPtr entry, 515 fsBitmapFormat format, fsBitmapFormatMask fmask, 516 FontPtr non_cachable_font) 517{ 518 FontBitmapEntryPtr bitmap; 519 char fileName[MAXFONTFILENAMELEN*2+1]; 520 int ret; 521 FontDirectoryPtr dir; 522 523 dir = (FontDirectoryPtr) fpe->private; 524 bitmap = &entry->u.bitmap; 525 if(!bitmap || !bitmap->renderer->OpenBitmap) 526 return BadFontName; 527 if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) 528 return BadFontName; 529 strcpy (fileName, dir->directory); 530 strcat (fileName, bitmap->fileName); 531 ret = (*bitmap->renderer->OpenBitmap) 532 (fpe, pFont, flags, entry, fileName, format, fmask, 533 non_cachable_font); 534 if (ret == Successful) 535 { 536 bitmap->pFont = *pFont; 537 (*pFont)->fpePrivate = (pointer) entry; 538 } 539 return ret; 540} 541 542int 543FontFileOpenBitmap (FontPathElementPtr fpe, FontPtr *pFont, 544 int flags, FontEntryPtr entry, 545 fsBitmapFormat format, fsBitmapFormatMask fmask) 546{ 547 return FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, fmask, 548 (FontPtr)0); 549} 550 551static int 552FontFileGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, 553 FontEntryPtr entry) 554{ 555 FontBitmapEntryPtr bitmap; 556 char fileName[MAXFONTFILENAMELEN*2+1]; 557 int ret; 558 FontDirectoryPtr dir; 559 560 dir = (FontDirectoryPtr) fpe->private; 561 bitmap = &entry->u.bitmap; 562 if (!bitmap || !bitmap->renderer->GetInfoBitmap) 563 return BadFontName; 564 if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) 565 return BadFontName; 566 strcpy (fileName, dir->directory); 567 strcat (fileName, bitmap->fileName); 568 ret = (*bitmap->renderer->GetInfoBitmap) (fpe, pFontInfo, entry, fileName); 569 return ret; 570} 571 572static void 573_FontFileAddScalableNames(FontNamesPtr names, FontNamesPtr scaleNames, 574 FontNamePtr nameptr, char *zeroChars, 575 FontScalablePtr vals, fsRange *ranges, 576 int nranges, int *max) 577{ 578 int i; 579 FontScalableRec zeroVals, tmpVals; 580 for (i = 0; i < scaleNames->nnames; i++) 581 { 582 char nameChars[MAXFONTNAMELEN]; 583 if (!*max) 584 return; 585 FontParseXLFDName (scaleNames->names[i], &zeroVals, 586 FONT_XLFD_REPLACE_NONE); 587 tmpVals = *vals; 588 if (FontFileCompleteXLFD (&tmpVals, &zeroVals)) 589 { 590 --*max; 591 592 strcpy (nameChars, scaleNames->names[i]); 593 if ((vals->values_supplied & PIXELSIZE_MASK) || 594 !(vals->values_supplied & PIXELSIZE_WILDCARD) || 595 vals->y == 0) 596 { 597 tmpVals.values_supplied = 598 (tmpVals.values_supplied & ~PIXELSIZE_MASK) | 599 (vals->values_supplied & PIXELSIZE_MASK); 600 tmpVals.pixel_matrix[0] = vals->pixel_matrix[0]; 601 tmpVals.pixel_matrix[1] = vals->pixel_matrix[1]; 602 tmpVals.pixel_matrix[2] = vals->pixel_matrix[2]; 603 tmpVals.pixel_matrix[3] = vals->pixel_matrix[3]; 604 } 605 if ((vals->values_supplied & POINTSIZE_MASK) || 606 !(vals->values_supplied & POINTSIZE_WILDCARD) || 607 vals->y == 0) 608 { 609 tmpVals.values_supplied = 610 (tmpVals.values_supplied & ~POINTSIZE_MASK) | 611 (vals->values_supplied & POINTSIZE_MASK); 612 tmpVals.point_matrix[0] = vals->point_matrix[0]; 613 tmpVals.point_matrix[1] = vals->point_matrix[1]; 614 tmpVals.point_matrix[2] = vals->point_matrix[2]; 615 tmpVals.point_matrix[3] = vals->point_matrix[3]; 616 } 617 if (vals->width <= 0) 618 tmpVals.width = 0; 619 if (vals->x == 0) 620 tmpVals.x = 0; 621 if (vals->y == 0) 622 tmpVals.y = 0; 623 tmpVals.ranges = ranges; 624 tmpVals.nranges = nranges; 625 FontParseXLFDName (nameChars, &tmpVals, 626 FONT_XLFD_REPLACE_VALUE); 627 /* If we're marking aliases with negative lengths, we 628 need to concoct a valid target name to follow it. 629 Otherwise we're done. */ 630 if (scaleNames->length[i] >= 0) 631 { 632 (void) AddFontNamesName (names, nameChars, 633 strlen (nameChars)); 634 /* If our original pattern matches the name from 635 the table and that name doesn't duplicate what 636 we just added, add the name from the table */ 637 if (strcmp(nameChars, scaleNames->names[i]) && 638 FontFileMatchName(scaleNames->names[i], 639 scaleNames->length[i], 640 nameptr) && 641 *max) 642 { 643 --*max; 644 (void) AddFontNamesName (names, scaleNames->names[i], 645 scaleNames->length[i]); 646 } 647 } 648 else 649 { 650 char *aliasName; 651 vals->ranges = ranges; 652 vals->nranges = nranges; 653 if (transfer_values_to_alias(zeroChars, 654 strlen(zeroChars), 655 scaleNames->names[++i], 656 &aliasName, vals)) 657 { 658 (void) AddFontNamesName (names, nameChars, 659 strlen (nameChars)); 660 names->length[names->nnames - 1] = 661 -names->length[names->nnames - 1]; 662 (void) AddFontNamesName (names, aliasName, 663 strlen (aliasName)); 664 /* If our original pattern matches the name from 665 the table and that name doesn't duplicate what 666 we just added, add the name from the table */ 667 if (strcmp(nameChars, scaleNames->names[i - 1]) && 668 FontFileMatchName(scaleNames->names[i - 1], 669 -scaleNames->length[i - 1], 670 nameptr) && 671 *max) 672 { 673 --*max; 674 (void) AddFontNamesName (names, 675 scaleNames->names[i - 1], 676 -scaleNames->length[i - 1]); 677 names->length[names->nnames - 1] = 678 -names->length[names->nnames - 1]; 679 (void) AddFontNamesName (names, aliasName, 680 strlen (aliasName)); 681 } 682 } 683 } 684 } 685 } 686} 687 688/* ARGSUSED */ 689static int 690_FontFileListFonts (pointer client, FontPathElementPtr fpe, 691 const char *pat, int len, int max, FontNamesPtr names, 692 int mark_aliases) 693{ 694 FontDirectoryPtr dir; 695 char lowerChars[MAXFONTNAMELEN], zeroChars[MAXFONTNAMELEN]; 696 FontNameRec lowerName; 697 FontNameRec zeroName; 698 FontNamesPtr scaleNames; 699 FontScalableRec vals; 700 fsRange *ranges; 701 int nranges; 702 int result = BadFontName; 703 704 if (len >= MAXFONTNAMELEN) 705 return AllocError; 706 dir = (FontDirectoryPtr) fpe->private; 707 CopyISOLatin1Lowered (lowerChars, pat, len); 708 lowerChars[len] = '\0'; 709 lowerName.name = lowerChars; 710 lowerName.length = len; 711 lowerName.ndashes = FontFileCountDashes (lowerChars, len); 712 713 /* Match XLFD patterns */ 714 715 strcpy (zeroChars, lowerChars); 716 if (lowerName.ndashes == 14 && 717 FontParseXLFDName (zeroChars, &vals, FONT_XLFD_REPLACE_ZERO)) 718 { 719 ranges = FontParseRanges(lowerChars, &nranges); 720 result = FontFileFindNamesInScalableDir (&dir->nonScalable, 721 &lowerName, max, names, 722 (FontScalablePtr)0, 723 (mark_aliases ? 724 LIST_ALIASES_AND_TARGET_NAMES : 725 NORMAL_ALIAS_BEHAVIOR) | 726 IGNORE_SCALABLE_ALIASES, 727 &max); 728 zeroName.name = zeroChars; 729 zeroName.length = strlen (zeroChars); 730 zeroName.ndashes = lowerName.ndashes; 731 732 /* Look for scalable names and aliases, adding scaled instances of 733 them to the output */ 734 735 /* Scalable names... */ 736 scaleNames = MakeFontNamesRecord (0); 737 if (!scaleNames) 738 { 739 if (ranges) free(ranges); 740 return AllocError; 741 } 742 FontFileFindNamesInScalableDir (&dir->scalable, &zeroName, max, 743 scaleNames, &vals, 744 mark_aliases ? 745 LIST_ALIASES_AND_TARGET_NAMES : 746 NORMAL_ALIAS_BEHAVIOR, (int *)0); 747 _FontFileAddScalableNames(names, scaleNames, &lowerName, 748 zeroChars, &vals, ranges, nranges, 749 &max); 750 FreeFontNames (scaleNames); 751 752 /* Scalable aliases... */ 753 scaleNames = MakeFontNamesRecord (0); 754 if (!scaleNames) 755 { 756 if (ranges) free(ranges); 757 return AllocError; 758 } 759 FontFileFindNamesInScalableDir (&dir->nonScalable, &zeroName, 760 max, scaleNames, &vals, 761 mark_aliases ? 762 LIST_ALIASES_AND_TARGET_NAMES : 763 NORMAL_ALIAS_BEHAVIOR, (int *)0); 764 _FontFileAddScalableNames(names, scaleNames, &lowerName, 765 zeroChars, &vals, ranges, nranges, 766 &max); 767 FreeFontNames (scaleNames); 768 769 if (ranges) free(ranges); 770 } 771 else 772 { 773 result = FontFileFindNamesInScalableDir (&dir->nonScalable, 774 &lowerName, max, names, 775 (FontScalablePtr)0, 776 mark_aliases ? 777 LIST_ALIASES_AND_TARGET_NAMES : 778 NORMAL_ALIAS_BEHAVIOR, 779 &max); 780 if (result == Successful) 781 result = FontFileFindNamesInScalableDir (&dir->scalable, 782 &lowerName, max, names, 783 (FontScalablePtr)0, 784 mark_aliases ? 785 LIST_ALIASES_AND_TARGET_NAMES : 786 NORMAL_ALIAS_BEHAVIOR, (int *)0); 787 } 788 return result; 789} 790 791typedef struct _LFWIData { 792 FontNamesPtr names; 793 int current; 794} LFWIDataRec, *LFWIDataPtr; 795 796int 797FontFileListFonts (pointer client, FontPathElementPtr fpe, const char *pat, 798 int len, int max, FontNamesPtr names) 799{ 800 return _FontFileListFonts (client, fpe, pat, len, max, names, 0); 801} 802 803int 804FontFileStartListFonts(pointer client, FontPathElementPtr fpe, 805 const char *pat, int len, int max, 806 pointer *privatep, int mark_aliases) 807{ 808 LFWIDataPtr data; 809 int ret; 810 811 data = malloc (sizeof *data); 812 if (!data) 813 return AllocError; 814 data->names = MakeFontNamesRecord (0); 815 if (!data->names) 816 { 817 free (data); 818 return AllocError; 819 } 820 ret = _FontFileListFonts (client, fpe, pat, len, 821 max, data->names, mark_aliases); 822 if (ret != Successful) 823 { 824 FreeFontNames (data->names); 825 free (data); 826 return ret; 827 } 828 data->current = 0; 829 *privatep = (pointer) data; 830 return Successful; 831} 832 833 834int 835FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, 836 const char *pat, int len, int max, 837 pointer *privatep) 838{ 839 return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0); 840} 841 842/* ARGSUSED */ 843static int 844FontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe, 845 char **namep, int *namelenp, 846 FontInfoPtr *pFontInfo) 847{ 848 FontDirectoryPtr dir; 849 char lowerName[MAXFONTNAMELEN]; 850 char fileName[MAXFONTFILENAMELEN*2 + 1]; 851 FontNameRec tmpName; 852 FontEntryPtr entry; 853 FontScalableRec vals; 854 FontScalableEntryPtr scalable; 855 FontScaledPtr scaled; 856 FontBitmapEntryPtr bitmap; 857 int ret; 858 Bool noSpecificSize; 859 int nranges; 860 fsRange *ranges; 861 862 char *name = *namep; 863 int namelen = *namelenp; 864 865 if (namelen >= MAXFONTNAMELEN) 866 return AllocError; 867 dir = (FontDirectoryPtr) fpe->private; 868 869 /* Match non-scalable pattern */ 870 CopyISOLatin1Lowered (lowerName, name, namelen); 871 lowerName[namelen] = '\0'; 872 ranges = FontParseRanges(lowerName, &nranges); 873 tmpName.name = lowerName; 874 tmpName.length = namelen; 875 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 876 if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) 877 bzero(&vals, sizeof(vals)); 878 if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && 879 tmpName.ndashes == 14 && 880 FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) 881 { 882 tmpName.length = strlen(lowerName); 883 entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); 884 } 885 886 if (entry) 887 { 888 switch (entry->type) { 889 case FONT_ENTRY_BITMAP: 890 bitmap = &entry->u.bitmap; 891 if (bitmap->pFont) 892 { 893 *pFontInfo = &bitmap->pFont->info; 894 ret = Successful; 895 } 896 else 897 { 898 ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); 899 } 900 break; 901 case FONT_ENTRY_ALIAS: 902 vals.nranges = nranges; 903 vals.ranges = ranges; 904 transfer_values_to_alias(entry->name.name, entry->name.length, 905 entry->u.alias.resolved, namep, &vals); 906 *namelenp = strlen (*namep); 907 ret = FontNameAlias; 908 break; 909 default: 910 ret = BadFontName; 911 } 912 } 913 else 914 { 915 ret = BadFontName; 916 } 917 918 if (ret != BadFontName) 919 { 920 if (ranges) free(ranges); 921 return ret; 922 } 923 924 /* Match XLFD patterns */ 925 CopyISOLatin1Lowered (lowerName, name, namelen); 926 lowerName[namelen] = '\0'; 927 tmpName.name = lowerName; 928 tmpName.length = namelen; 929 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 930 if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || 931 !(tmpName.length = strlen (lowerName), 932 entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, 933 &vals))) { 934 CopyISOLatin1Lowered (lowerName, name, namelen); 935 lowerName[namelen] = '\0'; 936 tmpName.name = lowerName; 937 tmpName.length = namelen; 938 tmpName.ndashes = FontFileCountDashes (lowerName, namelen); 939 entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); 940 if (entry) 941 { 942 strcpy(lowerName, entry->name.name); 943 tmpName.name = lowerName; 944 tmpName.length = entry->name.length; 945 tmpName.ndashes = entry->name.ndashes; 946 } 947 } 948 949 if (entry) 950 { 951 noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ 952 if (entry && entry->type == FONT_ENTRY_SCALABLE && 953 FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) 954 { 955 scalable = &entry->u.scalable; 956 scaled = FontFileFindScaledInstance (entry, &vals, noSpecificSize); 957 /* 958 * A scaled instance can occur one of two ways: 959 * 960 * Either the font has been scaled to this 961 * size already, in which case scaled->pFont 962 * will point at that font. 963 * 964 * Or a bitmap instance in this size exists, 965 * which is handled as if we got a pattern 966 * matching the bitmap font name. 967 */ 968 if (scaled) 969 { 970 if (scaled->pFont) 971 { 972 *pFontInfo = &scaled->pFont->info; 973 ret = Successful; 974 } 975 else if (scaled->bitmap) 976 { 977 entry = scaled->bitmap; 978 bitmap = &entry->u.bitmap; 979 if (bitmap->pFont) 980 { 981 *pFontInfo = &bitmap->pFont->info; 982 ret = Successful; 983 } 984 else 985 { 986 ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); 987 } 988 } 989 else /* "cannot" happen */ 990 { 991 ret = BadFontName; 992 } 993 } 994 else 995 { 996 { 997 char origName[MAXFONTNAMELEN]; 998 999 CopyISOLatin1Lowered (origName, name, namelen); 1000 origName[namelen] = '\0'; 1001 vals.xlfdName = origName; 1002 vals.ranges = ranges; 1003 vals.nranges = nranges; 1004 1005 /* Make a new scaled instance */ 1006 if (strlen(dir->directory) + strlen(scalable->fileName) >= 1007 sizeof(fileName)) { 1008 ret = BadFontName; 1009 } else { 1010 strcpy (fileName, dir->directory); 1011 strcat (fileName, scalable->fileName); 1012 if (scalable->renderer->GetInfoScalable) 1013 ret = (*scalable->renderer->GetInfoScalable) 1014 (fpe, *pFontInfo, entry, &tmpName, fileName, 1015 &vals); 1016 else if (scalable->renderer->GetInfoBitmap) 1017 ret = (*scalable->renderer->GetInfoBitmap) 1018 (fpe, *pFontInfo, entry, fileName); 1019 } 1020 if (ranges) { 1021 free(ranges); 1022 ranges = NULL; 1023 } 1024 } 1025 } 1026 if (ret == Successful) return ret; 1027 } 1028 CopyISOLatin1Lowered (lowerName, name, namelen); 1029 tmpName.length = namelen; 1030 } 1031 else 1032 ret = BadFontName; 1033 1034 if (ranges) 1035 free(ranges); 1036 return ret; 1037} 1038 1039int 1040FontFileListNextFontWithInfo(pointer client, FontPathElementPtr fpe, 1041 char **namep, int *namelenp, 1042 FontInfoPtr *pFontInfo, 1043 int *numFonts, pointer private) 1044{ 1045 LFWIDataPtr data = (LFWIDataPtr) private; 1046 int ret; 1047 char *name; 1048 int namelen; 1049 1050 if (data->current == data->names->nnames) 1051 { 1052 FreeFontNames (data->names); 1053 free (data); 1054 return BadFontName; 1055 } 1056 name = data->names->names[data->current]; 1057 namelen = data->names->length[data->current]; 1058 ret = FontFileListOneFontWithInfo (client, fpe, &name, &namelen, pFontInfo); 1059 if (ret == BadFontName) 1060 ret = AllocError; 1061 *namep = name; 1062 *namelenp = namelen; 1063 ++data->current; 1064 *numFonts = data->names->nnames - data->current; 1065 return ret; 1066} 1067 1068int 1069FontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, 1070 const char *pat, int len, int max, 1071 pointer *privatep) 1072{ 1073 return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1); 1074} 1075 1076int 1077FontFileListNextFontOrAlias(pointer client, FontPathElementPtr fpe, 1078 char **namep, int *namelenp, char **resolvedp, 1079 int *resolvedlenp, pointer private) 1080{ 1081 LFWIDataPtr data = (LFWIDataPtr) private; 1082 int ret; 1083 char *name; 1084 int namelen; 1085 1086 if (data->current == data->names->nnames) 1087 { 1088 FreeFontNames (data->names); 1089 free (data); 1090 return BadFontName; 1091 } 1092 name = data->names->names[data->current]; 1093 namelen = data->names->length[data->current]; 1094 1095 /* If this is a real font name... */ 1096 if (namelen >= 0) 1097 { 1098 *namep = name; 1099 *namelenp = namelen; 1100 ret = Successful; 1101 } 1102 /* Else if an alias */ 1103 else 1104 { 1105 /* Tell the caller that this is an alias... let him resolve it to 1106 see if it's valid */ 1107 *namep = name; 1108 *namelenp = -namelen; 1109 *resolvedp = data->names->names[++data->current]; 1110 *resolvedlenp = data->names->length[data->current]; 1111 ret = FontNameAlias; 1112 } 1113 1114 ++data->current; 1115 return ret; 1116} 1117 1118void 1119FontFileRegisterLocalFpeFunctions (void) 1120{ 1121 RegisterFPEFunctions(FontFileNameCheck, 1122 FontFileInitFPE, 1123 FontFileFreeFPE, 1124 FontFileResetFPE, 1125 FontFileOpenFont, 1126 FontFileCloseFont, 1127 FontFileListFonts, 1128 FontFileStartListFontsWithInfo, 1129 FontFileListNextFontWithInfo, 1130 NULL, 1131 NULL, 1132 NULL, 1133 FontFileStartListFontsAndAliases, 1134 FontFileListNextFontOrAlias, 1135 FontFileEmptyBitmapSource); 1136} 1137