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