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