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