bitscale.c revision 23a0898a
1/* $Xorg: bitscale.c,v 1.5 2001/02/09 02:04:02 xorgcvs Exp $ */ 2/* 3 4Copyright 1991, 1994, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included 13in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall 24not be used in advertising or otherwise to promote the sale, use or 25other dealings in this Software without prior written authorization 26from The Open Group. 27 28*/ 29/* $XFree86: xc/lib/font/bitmap/bitscale.c,v 3.29tsi Exp $ */ 30 31/* 32 * Author: Keith Packard, MIT X Consortium 33 */ 34 35#ifdef HAVE_CONFIG_H 36#include <config.h> 37#endif 38 39/* 40 * Translate monolithic #defines to modular definitions 41 */ 42 43#ifdef PCFFORMAT 44#define XFONT_PCFFORMAT 1 45#endif 46 47#ifdef SNFFORMAT 48#define XFONT_SNFFORMAT 1 49#endif 50 51#ifdef BDFFORMAT 52#define XFONT_BDFFORMAT 1 53#endif 54 55#include <X11/fonts/fntfilst.h> 56#include <X11/fonts/bitmap.h> 57#include <X11/fonts/fontutil.h> 58#ifndef FONTMODULE 59#ifdef _XOPEN_SOURCE 60#include <math.h> 61#else 62#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ 63#include <math.h> 64#undef _XOPEN_SOURCE 65#endif 66#endif 67 68#ifndef MAX 69#define MAX(a,b) (((a)>(b)) ? a : b) 70#endif 71 72/* Should get this from elsewhere */ 73extern unsigned long serverGeneration; 74 75static void bitmapUnloadScalable (FontPtr pFont); 76static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci, 77 CharInfoPtr pci, double *inv_xform, 78 double widthMult, double heightMult ); 79static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf, 80 double widthMult, double heightMult, 81 FontScalablePtr vals); 82static FontPtr PrinterScaleBitmaps(FontPtr pf, FontPtr opf, 83 double widthMult, double heightMult, 84 FontScalablePtr vals); 85 86enum scaleType { 87 atom, truncate_atom, pixel_size, point_size, resolution_x, 88 resolution_y, average_width, scaledX, scaledY, unscaled, fontname, 89 raw_ascent, raw_descent, raw_pixelsize, raw_pointsize, 90 raw_average_width, uncomputed 91}; 92 93typedef struct _fontProp { 94 char *name; 95 Atom atom; 96 enum scaleType type; 97} fontProp; 98 99typedef FontPtr (*ScaleFunc) ( FontPtr /* pf */, 100 FontPtr /* opf */, 101 double /* widthMult */, 102 double /* heightMult */, 103 FontScalablePtr /* vals */); 104 105/* These next two arrays must be kept in step with the renderer array */ 106static const ScaleFunc scale[] = 107{ 108#if XFONT_PCFFORMAT 109 BitmapScaleBitmaps, 110 BitmapScaleBitmaps, 111#ifdef X_GZIP_FONT_COMPRESSION 112 BitmapScaleBitmaps, 113#endif 114#endif 115#if XFONT_SNFFORMAT 116 BitmapScaleBitmaps, 117 BitmapScaleBitmaps, 118#ifdef X_GZIP_FONT_COMPRESSION 119 BitmapScaleBitmaps, 120#endif 121#endif 122#if XFONT_BDFFORMAT 123 BitmapScaleBitmaps, 124 BitmapScaleBitmaps, 125#ifdef X_GZIP_FONT_COMPRESSION 126 BitmapScaleBitmaps, 127#endif 128#endif 129#if XFONT_PCFFORMAT 130 PrinterScaleBitmaps, 131#endif 132}; 133 134static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe, 135 FontEntryPtr entry, 136 FontScalablePtr vals, 137 FontScalablePtr best, 138 double *dxp, double *dyp, 139 double *sdxp, double *sdyp, 140 FontPathElementPtr *fpep ); 141static FontEntryPtr FindPmfToScale ( FontPathElementPtr fpe, 142 FontEntryPtr entry, 143 FontScalablePtr vals, 144 FontScalablePtr best, 145 double *dxp, double *dyp, 146 double *sdxp, double *sdyp, 147 FontPathElementPtr *fpep ); 148 149typedef FontEntryPtr (*FindToScale) (FontPathElementPtr fpe, 150 FontEntryPtr entry, 151 FontScalablePtr vals, 152 FontScalablePtr best, 153 double *dxp, double *dyp, 154 double *sdxp, double *sdyp, 155 FontPathElementPtr *fpep); 156static const FindToScale find_scale[] = 157{ 158#if XFONT_PCFFORMAT 159 FindBestToScale, 160 FindBestToScale, 161#ifdef X_GZIP_FONT_COMPRESSION 162 FindBestToScale, 163#endif 164#endif 165#if XFONT_SNFFORMAT 166 FindBestToScale, 167 FindBestToScale, 168#ifdef X_GZIP_FONT_COMPRESSION 169 FindBestToScale, 170#endif 171#endif 172#if XFONT_BDFFORMAT 173 FindBestToScale, 174 FindBestToScale, 175#ifdef X_GZIP_FONT_COMPRESSION 176 FindBestToScale, 177#endif 178#endif 179#if XFONT_PCFFORMAT 180 FindPmfToScale, 181#endif 182}; 183 184static unsigned long bitscaleGeneration = 0; /* initialization flag */ 185 186static fontProp fontNamePropTable[] = { 187 { "FOUNDRY", 0, atom }, 188 { "FAMILY_NAME", 0, atom }, 189 { "WEIGHT_NAME", 0, atom }, 190 { "SLANT", 0, atom }, 191 { "SETWIDTH_NAME", 0, atom }, 192 { "ADD_STYLE_NAME", 0, atom }, 193 { "PIXEL_SIZE", 0, pixel_size }, 194 { "POINT_SIZE", 0, point_size }, 195 { "RESOLUTION_X", 0, resolution_x }, 196 { "RESOLUTION_Y", 0, resolution_y }, 197 { "SPACING", 0, atom }, 198 { "AVERAGE_WIDTH", 0, average_width }, 199 { "CHARSET_REGISTRY", 0, atom }, 200 { "CHARSET_ENCODING", 0, truncate_atom }, 201 { "FONT", 0, fontname }, 202 { "RAW_ASCENT", 0, raw_ascent }, 203 { "RAW_DESCENT", 0, raw_descent }, 204 { "RAW_PIXEL_SIZE", 0, raw_pixelsize }, 205 { "RAW_POINT_SIZE", 0, raw_pointsize }, 206 { "RAW_AVERAGE_WIDTH", 0, raw_average_width } 207}; 208 209#define TRANSFORM_POINT(matrix, x, y, dest) \ 210 ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ 211 (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) 212 213#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ 214 ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ 215 (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ 216 (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ 217 (asc) < (data)[1] ? (asc) = (data)[1] : 0) 218 219#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp)) 220 221/* Warning: order of the next two tables is critically interdependent. 222 Location of "unscaled" properties at the end of fontPropTable[] 223 is important. */ 224 225static fontProp fontPropTable[] = { 226 { "MIN_SPACE", 0, scaledX }, 227 { "NORM_SPACE", 0, scaledX }, 228 { "MAX_SPACE", 0, scaledX }, 229 { "END_SPACE", 0, scaledX }, 230 { "AVG_CAPITAL_WIDTH", 0, scaledX }, 231 { "AVG_LOWERCASE_WIDTH", 0, scaledX }, 232 { "QUAD_WIDTH", 0, scaledX }, 233 { "FIGURE_WIDTH", 0, scaledX }, 234 { "SUPERSCRIPT_X", 0, scaledX }, 235 { "SUPERSCRIPT_Y", 0, scaledY }, 236 { "SUBSCRIPT_X", 0, scaledX }, 237 { "SUBSCRIPT_Y", 0, scaledY }, 238 { "SUPERSCRIPT_SIZE", 0, scaledY }, 239 { "SUBSCRIPT_SIZE", 0, scaledY }, 240 { "SMALL_CAP_SIZE", 0, scaledY }, 241 { "UNDERLINE_POSITION", 0, scaledY }, 242 { "UNDERLINE_THICKNESS", 0, scaledY }, 243 { "STRIKEOUT_ASCENT", 0, scaledY }, 244 { "STRIKEOUT_DESCENT", 0, scaledY }, 245 { "CAP_HEIGHT", 0, scaledY }, 246 { "X_HEIGHT", 0, scaledY }, 247 { "ITALIC_ANGLE", 0, unscaled }, 248 { "RELATIVE_SETWIDTH", 0, unscaled }, 249 { "RELATIVE_WEIGHT", 0, unscaled }, 250 { "WEIGHT", 0, unscaled }, 251 { "DESTINATION", 0, unscaled }, 252 { "PCL_FONT_NAME", 0, unscaled }, 253 { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled } 254}; 255 256/* sleazy way to shut up the compiler */ 257#define zerohack (enum scaleType)0 258 259static fontProp rawFontPropTable[] = { 260 { "RAW_MIN_SPACE", 0, }, 261 { "RAW_NORM_SPACE", 0, }, 262 { "RAW_MAX_SPACE", 0, }, 263 { "RAW_END_SPACE", 0, }, 264 { "RAW_AVG_CAPITAL_WIDTH", 0, }, 265 { "RAW_AVG_LOWERCASE_WIDTH", 0, }, 266 { "RAW_QUAD_WIDTH", 0, }, 267 { "RAW_FIGURE_WIDTH", 0, }, 268 { "RAW_SUPERSCRIPT_X", 0, }, 269 { "RAW_SUPERSCRIPT_Y", 0, }, 270 { "RAW_SUBSCRIPT_X", 0, }, 271 { "RAW_SUBSCRIPT_Y", 0, }, 272 { "RAW_SUPERSCRIPT_SIZE", 0, }, 273 { "RAW_SUBSCRIPT_SIZE", 0, }, 274 { "RAW_SMALL_CAP_SIZE", 0, }, 275 { "RAW_UNDERLINE_POSITION", 0, }, 276 { "RAW_UNDERLINE_THICKNESS", 0, }, 277 { "RAW_STRIKEOUT_ASCENT", 0, }, 278 { "RAW_STRIKEOUT_DESCENT", 0, }, 279 { "RAW_CAP_HEIGHT", 0, }, 280 { "RAW_X_HEIGHT", 0, } 281}; 282 283static void 284initFontPropTable(void) 285{ 286 int i; 287 fontProp *t; 288 289 i = sizeof(fontNamePropTable) / sizeof(fontProp); 290 for (t = fontNamePropTable; i; i--, t++) 291 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 292 293 i = sizeof(fontPropTable) / sizeof(fontProp); 294 for (t = fontPropTable; i; i--, t++) 295 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 296 297 i = sizeof(rawFontPropTable) / sizeof(fontProp); 298 for (t = rawFontPropTable; i; i--, t++) 299 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 300} 301 302#if 0 303static FontEntryPtr 304GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name) 305{ 306 FontDirectoryPtr dir; 307 308 dir = (FontDirectoryPtr) fpe->private; 309 return FontFileFindNameInDir (&dir->scalable, name); 310} 311#endif 312 313static double 314get_matrix_horizontal_component(double *matrix) 315{ 316 return hypot(matrix[0], matrix[1]); 317} 318 319static double 320get_matrix_vertical_component(double *matrix) 321{ 322 return hypot(matrix[2], matrix[3]); 323} 324 325 326static Bool 327ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to, 328 double *dx, double *dy, double *sdx, double *sdy, 329 double *rescale_x) 330{ 331 double srcpixelset, destpixelset, srcpixel, destpixel; 332 333 srcpixelset = get_matrix_horizontal_component(from->pixel_matrix); 334 destpixelset = get_matrix_horizontal_component(to->pixel_matrix); 335 srcpixel = get_matrix_vertical_component(from->pixel_matrix); 336 destpixel = get_matrix_vertical_component(to->pixel_matrix); 337 338 if (srcpixelset >= EPS) 339 { 340 *dx = destpixelset / srcpixelset; 341 *sdx = 1000.0 / srcpixelset; 342 } 343 else 344 *sdx = *dx = 0; 345 346 *rescale_x = 1.0; 347 348 /* If client specified a width, it overrides setsize; in this 349 context, we interpret width as applying to the font before any 350 rotation, even though that's not what is ultimately returned in 351 the width field. */ 352 if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS) 353 { 354 double rescale = (double)to->width / (double)from->width; 355 356 /* If the client specified a transformation matrix, the rescaling 357 for width does *not* override the setsize. Instead, just check 358 for consistency between the setsize from the matrix and the 359 setsize that would result from rescaling according to the width. 360 This assumes (perhaps naively) that the width is correctly 361 reported in the name. As an interesting side effect, this test 362 may result in choosing a different source bitmap (one that 363 scales consistently between the setsize *and* the width) than it 364 would choose if a width were not specified. Sort of a hidden 365 multiple-master functionality. */ 366 if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || 367 (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) 368 { 369 /* Reject if resulting width difference is >= 1 pixel */ 370 if (fabs(rescale * from->width - *dx * from->width) >= 10) 371 return FALSE; 372 } 373 else 374 { 375 *rescale_x = rescale/(*dx); 376 *dx = rescale; 377 } 378 } 379 380 if (srcpixel >= EPS) 381 { 382 *dy = destpixel / srcpixel; 383 *sdy = 1000.0 / srcpixel; 384 } 385 else 386 *sdy = *dy = 0; 387 388 return TRUE; 389} 390 391/* favor enlargement over reduction because of aliasing resulting 392 from reduction */ 393#define SCORE(m,s) \ 394if (m >= 1.0) { \ 395 if (m == 1.0) \ 396 score += (16 * s); \ 397 else if (m == 2.0) \ 398 score += (4 * s); \ 399 else \ 400 score += (int)(((double)(3 * s)) / m); \ 401} else { \ 402 score += (int)(((double)(2 * s)) * m); \ 403} 404 405/* don't need to favor enlargement when looking for bitmap that can 406 be used unscalable */ 407#define SCORE2(m,s) \ 408if (m >= 1.0) \ 409 score += (int)(((double)(8 * s)) / m); \ 410else \ 411 score += (int)(((double)(8 * s)) * m); 412 413static FontEntryPtr 414FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry, 415 FontScalablePtr vals, FontScalablePtr best, 416 double *dxp, double *dyp, 417 double *sdxp, double *sdyp, 418 FontPathElementPtr *fpep) 419{ 420 FontScalableRec temp; 421 int source, i; 422 int best_score, best_unscaled_score, 423 score; 424 double dx = 0.0, sdx = 0.0, dx_amount = 0.0, 425 dy = 0.0, sdy = 0.0, dy_amount = 0.0, 426 best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0, 427 best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0, 428 best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0, 429 rescale_x = 0.0, best_rescale_x = 0.0, 430 best_unscaled_rescale_x = 0.0; 431 FontEntryPtr zero; 432 FontNameRec zeroName; 433 char zeroChars[MAXFONTNAMELEN]; 434 FontDirectoryPtr dir; 435 FontScaledPtr scaled; 436 FontScalableExtraPtr extra; 437 FontScaledPtr best_scaled, best_unscaled; 438 FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL; 439 FontEntryPtr bitmap = NULL; 440 FontEntryPtr result; 441 int aliascount = 20; 442 FontPathElementPtr bitmap_fpe = NULL; 443 FontNameRec xlfdName; 444 445 /* find the best match */ 446 rescale_x = 1.0; 447 best_scaled = 0; 448 best_score = 0; 449 best_unscaled = 0; 450 best_unscaled_score = -1; 451 best_dx_amount = best_dy_amount = HUGE_VAL; 452 memcpy (zeroChars, entry->name.name, entry->name.length); 453 zeroChars[entry->name.length] = '\0'; 454 zeroName.name = zeroChars; 455 FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO); 456 zeroName.length = strlen (zeroChars); 457 zeroName.ndashes = entry->name.ndashes; 458 xlfdName.name = vals->xlfdName; 459 xlfdName.length = strlen(xlfdName.name); 460 xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length); 461 restart_bestscale_loop: ; 462 /* 463 * Look through all the registered bitmap sources for 464 * the same zero name as ours; entries along that one 465 * can be scaled as desired. 466 */ 467 for (source = 0; source < FontFileBitmapSources.count; source++) 468 { 469 /* There might already be a bitmap that satisfies the request 470 but didn't have a zero name that was found by the scalable 471 font matching logic. Keep track if there is. */ 472 if (bitmap == NULL && vals->xlfdName != NULL) 473 { 474 bitmap_fpe = FontFileBitmapSources.fpe[source]; 475 dir = (FontDirectoryPtr) bitmap_fpe->private; 476 bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName); 477 if (bitmap && bitmap->type != FONT_ENTRY_BITMAP) 478 { 479 if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0) 480 { 481 aliascount--; 482 xlfdName.name = bitmap->u.alias.resolved; 483 xlfdName.length = strlen(xlfdName.name); 484 xlfdName.ndashes = FontFileCountDashes(xlfdName.name, 485 xlfdName.length); 486 bitmap = NULL; 487 goto restart_bestscale_loop; 488 } 489 else 490 bitmap = NULL; 491 } 492 } 493 494 if (FontFileBitmapSources.fpe[source] == fpe) 495 zero = entry; 496 else 497 { 498 dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; 499 zero = FontFileFindNameInDir (&dir->scalable, &zeroName); 500 if (!zero) 501 continue; 502 } 503 extra = zero->u.scalable.extra; 504 for (i = 0; i < extra->numScaled; i++) 505 { 506 scaled = &extra->scaled[i]; 507 if (!scaled->bitmap) 508 continue; 509 if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy, 510 &rescale_x)) 511 continue; 512 score = 0; 513 dx_amount = dx; 514 dy_amount = dy; 515 SCORE(dy_amount, 10); 516 SCORE(dx_amount, 1); 517 if ((score > best_score) || 518 ((score == best_score) && 519 ((dy_amount < best_dy_amount) || 520 ((dy_amount == best_dy_amount) && 521 (dx_amount < best_dx_amount))))) 522 { 523 best_fpe = FontFileBitmapSources.fpe[source]; 524 best_scaled = scaled; 525 best_score = score; 526 best_dx = dx; 527 best_dy = dy; 528 best_sdx = sdx; 529 best_sdy = sdy; 530 best_dx_amount = dx_amount; 531 best_dy_amount = dy_amount; 532 best_rescale_x = rescale_x; 533 } 534 /* Is this font a candidate for use without ugly rescaling? */ 535 if (fabs(dx) > EPS && fabs(dy) > EPS && 536 fabs(vals->pixel_matrix[0] * rescale_x - 537 scaled->vals.pixel_matrix[0]) < 1 && 538 fabs(vals->pixel_matrix[1] * rescale_x - 539 scaled->vals.pixel_matrix[1]) < EPS && 540 fabs(vals->pixel_matrix[2] - 541 scaled->vals.pixel_matrix[2]) < EPS && 542 fabs(vals->pixel_matrix[3] - 543 scaled->vals.pixel_matrix[3]) < 1) 544 { 545 /* Yes. The pixel sizes are close on the diagonal and 546 extremely close off the diagonal. */ 547 score = 0; 548 SCORE2(vals->pixel_matrix[3] / 549 scaled->vals.pixel_matrix[3], 10); 550 SCORE2(vals->pixel_matrix[0] * rescale_x / 551 scaled->vals.pixel_matrix[0], 1); 552 if (score > best_unscaled_score) 553 { 554 best_unscaled_fpe = FontFileBitmapSources.fpe[source]; 555 best_unscaled = scaled; 556 best_unscaled_sdx = sdx / dx; 557 best_unscaled_sdy = sdy / dy; 558 best_unscaled_score = score; 559 best_unscaled_rescale_x = rescale_x; 560 } 561 } 562 } 563 } 564 if (best_unscaled) 565 { 566 *best = best_unscaled->vals; 567 *fpep = best_unscaled_fpe; 568 *dxp = 1.0; 569 *dyp = 1.0; 570 *sdxp = best_unscaled_sdx; 571 *sdyp = best_unscaled_sdy; 572 rescale_x = best_unscaled_rescale_x; 573 result = best_unscaled->bitmap; 574 } 575 else if (best_scaled) 576 { 577 *best = best_scaled->vals; 578 *fpep = best_fpe; 579 *dxp = best_dx; 580 *dyp = best_dy; 581 *sdxp = best_sdx; 582 *sdyp = best_sdy; 583 rescale_x = best_rescale_x; 584 result = best_scaled->bitmap; 585 } 586 else 587 result = NULL; 588 589 if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0)) 590 { 591 *fpep = bitmap_fpe; 592 FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE); 593 if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x)) 594 result = bitmap; 595 else 596 result = NULL; 597 } 598 599 if (result && rescale_x != 1.0) 600 { 601 /* We have rescaled horizontally due to an XLFD width field. Change 602 the matrix appropriately */ 603 vals->pixel_matrix[0] *= rescale_x; 604 vals->pixel_matrix[1] *= rescale_x; 605#ifdef NOTDEF 606 /* This would force the pointsize and pixelsize fields in the 607 FONT property to display as matrices to more accurately 608 report the font being supplied. It might also break existing 609 applications that expect a single number in that field. */ 610 vals->values_supplied = 611 vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) | 612 PIXELSIZE_ARRAY; 613#else /* NOTDEF */ 614 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; 615#endif /* NOTDEF */ 616 /* Recompute and reround the FontScalablePtr values after 617 rescaling for the new width. */ 618 FontFileCompleteXLFD(vals, vals); 619 } 620 621 return result; 622} 623 624static FontEntryPtr 625FindPmfToScale(FontPathElementPtr fpe, FontEntryPtr entry, 626 FontScalablePtr vals, FontScalablePtr best, 627 double *dxp, double *dyp, 628 double *sdxp, double *sdyp, 629 FontPathElementPtr *fpep) 630{ 631 FontEntryPtr result = NULL; 632 FontScaledPtr scaled; 633 FontScalableExtraPtr extra; 634 int i; 635 636 extra = entry->u.scalable.extra; 637 for (i = 0; i < extra->numScaled; i++) 638 { 639 double rescale_x; 640 641 scaled = &extra->scaled[i]; 642 if (!scaled->bitmap) 643 continue; 644 if (!ComputeScaleFactors(&scaled->vals, vals, dxp, dyp, sdxp, sdyp, 645 &rescale_x)) 646 continue; 647 *best = scaled->vals; 648 *fpep = fpe; 649 result = scaled->bitmap; 650 if (rescale_x != 1.0) 651 { 652 /* We have rescaled horizontally due to an XLFD width field. Change 653 the matrix appropriately */ 654 vals->pixel_matrix[0] *= rescale_x; 655 vals->pixel_matrix[1] *= rescale_x; 656#ifdef NOTDEF 657 /* This would force the pointsize and pixelsize fields in the 658 FONT property to display as matrices to more accurately 659 report the font being supplied. It might also break existing 660 applications that expect a single number in that field. */ 661 vals->values_supplied = 662 vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) | 663 PIXELSIZE_ARRAY; 664#else /* NOTDEF */ 665 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; 666#endif /* NOTDEF */ 667 /* Recompute and reround the FontScalablePtr values after 668 rescaling for the new width. */ 669 FontFileCompleteXLFD(vals, vals); 670 } 671 break; 672 } 673 return result; 674} 675 676static long 677doround(double x) 678{ 679 return (x >= 0) ? (long)(x + .5) : (long)(x - .5); 680} 681 682static int 683computeProps(FontPropPtr pf, char *wasStringProp, 684 FontPropPtr npf, char *isStringProp, 685 unsigned int nprops, double xfactor, double yfactor, 686 double sXfactor, double sYfactor) 687{ 688 int n; 689 int count; 690 fontProp *t; 691 double rawfactor = 0.0; 692 693 for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) { 694 n = sizeof(fontPropTable) / sizeof(fontProp); 695 for (t = fontPropTable; n && (t->atom != pf->name); n--, t++); 696 if (!n) 697 continue; 698 699 switch (t->type) { 700 case scaledX: 701 npf->value = doround(xfactor * (double)pf->value); 702 rawfactor = sXfactor; 703 break; 704 case scaledY: 705 npf->value = doround(yfactor * (double)pf->value); 706 rawfactor = sYfactor; 707 break; 708 case unscaled: 709 npf->value = pf->value; 710 npf->name = pf->name; 711 npf++; 712 count++; 713 *isStringProp++ = *wasStringProp; 714 break; 715 default: 716 break; 717 } 718 if (t->type != unscaled) 719 { 720 npf->name = pf->name; 721 npf++; 722 count++; 723 npf->value = doround(rawfactor * (double)pf->value); 724 npf->name = rawFontPropTable[t - fontPropTable].atom; 725 npf++; 726 count++; 727 *isStringProp++ = *wasStringProp; 728 *isStringProp++ = *wasStringProp; 729 } 730 } 731 return count; 732} 733 734 735static int 736ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */ 737 char *name, /* name of resulting font */ 738 FontScalablePtr vals, 739 double dx, double dy, /* scale factors in x and y */ 740 double sdx, double sdy, /* directions */ 741 long sWidth, /* 1000-pixel average width */ 742 FontPropPtr *pProps, /* returns properties; 743 preallocated */ 744 char **pIsStringProp) /* return booleans; 745 preallocated */ 746{ 747 int n; 748 char *ptr1 = NULL, *ptr2 = NULL; 749 char *ptr3; 750 FontPropPtr fp; 751 fontProp *fpt; 752 char *isStringProp; 753 int nProps; 754 755 if (bitscaleGeneration != serverGeneration) { 756 initFontPropTable(); 757 bitscaleGeneration = serverGeneration; 758 } 759 nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) + 760 sizeof(rawFontPropTable) / sizeof(fontProp); 761 fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps); 762 *pProps = fp; 763 if (!fp) { 764 fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n", 765 (unsigned long)sizeof(FontPropRec), nProps); 766 return 1; 767 } 768 isStringProp = (char *) xalloc (nProps); 769 *pIsStringProp = isStringProp; 770 if (!isStringProp) 771 { 772 fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps); 773 xfree (fp); 774 return 1; 775 } 776 ptr2 = name; 777 for (fpt = fontNamePropTable, n = NPROPS; 778 n; 779 fp++, fpt++, n--, isStringProp++) 780 { 781 782 if (*ptr2) 783 { 784 ptr1 = ptr2 + 1; 785 if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0'); 786 } 787 788 *isStringProp = 0; 789 switch (fpt->type) { 790 case atom: 791 fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE); 792 *isStringProp = 1; 793 break; 794 case truncate_atom: 795 for (ptr3 = ptr1; *ptr3; ptr3++) 796 if (*ptr3 == '[') 797 break; 798 if (!*ptr3) ptr3 = ptr2; 799 fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE); 800 *isStringProp = 1; 801 break; 802 case pixel_size: 803 fp->value = doround(vals->pixel_matrix[3]); 804 break; 805 case point_size: 806 fp->value = doround(vals->point_matrix[3] * 10.0); 807 break; 808 case resolution_x: 809 fp->value = vals->x; 810 break; 811 case resolution_y: 812 fp->value = vals->y; 813 break; 814 case average_width: 815 fp->value = vals->width; 816 break; 817 case fontname: 818 fp->value = MakeAtom(name, strlen(name), TRUE); 819 *isStringProp = 1; 820 break; 821 case raw_ascent: 822 fp->value = sourceFontInfo->fontAscent * sdy; 823 break; 824 case raw_descent: 825 fp->value = sourceFontInfo->fontDescent * sdy; 826 break; 827 case raw_pointsize: 828 fp->value = (long)(72270.0 / (double)vals->y + .5); 829 break; 830 case raw_pixelsize: 831 fp->value = 1000; 832 break; 833 case raw_average_width: 834 fp->value = sWidth; 835 break; 836 default: 837 break; 838 } 839 fp->name = fpt->atom; 840 } 841 n = NPROPS; 842 n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp, 843 fp, isStringProp, sourceFontInfo->nprops, dx, dy, 844 sdx, sdy); 845 return n; 846} 847 848 849static int 850compute_xform_matrix(FontScalablePtr vals, double dx, double dy, 851 double *xform, double *inv_xform, 852 double *xmult, double *ymult) 853{ 854 double det; 855 double pixel = get_matrix_vertical_component(vals->pixel_matrix); 856 double pixelset = get_matrix_horizontal_component(vals->pixel_matrix); 857 858 if (pixel < EPS || pixelset < EPS) return 0; 859 860 /* Initialize the transformation matrix to the scaling factors */ 861 xform[0] = dx / pixelset; 862 xform[1] = xform[2] = 0.0; 863 xform[3] = dy / pixel; 864 865/* Inline matrix multiply -- somewhat ugly to minimize register usage */ 866#define MULTIPLY_XFORM(a,b,c,d) \ 867{ \ 868 register double aa = (a), bb = (b), cc = (c), dd = (d); \ 869 register double temp; \ 870 temp = aa * xform[0] + cc * xform[1]; \ 871 aa = aa * xform[2] + cc * xform[3]; \ 872 xform[1] = bb * xform[0] + dd * xform[1]; \ 873 xform[3] = bb * xform[2] + dd * xform[3]; \ 874 xform[0] = temp; \ 875 xform[2] = aa; \ 876} 877 878 /* Rescale the transformation matrix for size of source font */ 879 MULTIPLY_XFORM(vals->pixel_matrix[0], 880 vals->pixel_matrix[1], 881 vals->pixel_matrix[2], 882 vals->pixel_matrix[3]); 883 884 *xmult = xform[0]; 885 *ymult = xform[3]; 886 887 888 if (inv_xform == NULL) return 1; 889 890 /* Compute the determinant for use in inverting the matrix. */ 891 det = xform[0] * xform[3] - xform[1] * xform[2]; 892 893 /* If the determinant is tiny or zero, give up */ 894 if (fabs(det) < EPS) return 0; 895 896 /* Compute the inverse */ 897 inv_xform[0] = xform[3] / det; 898 inv_xform[1] = -xform[1] / det; 899 inv_xform[2] = -xform[2] / det; 900 inv_xform[3] = xform[0] / det; 901 902 return 1; 903} 904 905/* 906 * ScaleFont 907 * returns a pointer to the new scaled font, or NULL (due to AllocError). 908 */ 909static FontPtr 910ScaleFont(FontPtr opf, /* originating font */ 911 double widthMult, /* glyphs width scale factor */ 912 double heightMult, /* glyphs height scale factor */ 913 double sWidthMult, /* scalable glyphs width scale factor */ 914 double sHeightMult, /* scalable glyphs height scale factor */ 915 FontScalablePtr vals, 916 double *newWidthMult, /* return: X component of glyphs width 917 scale factor */ 918 double *newHeightMult, /* return: Y component of glyphs height 919 scale factor */ 920 long *sWidth) /* return: average 1000-pixel width */ 921{ 922 FontPtr pf; 923 FontInfoPtr pfi, 924 opfi; 925 BitmapFontPtr bitmapFont, 926 obitmapFont; 927 CharInfoPtr pci, 928 opci; 929 int nchars = 0; /* how many characters in the font */ 930 int i; 931 int firstCol, lastCol, firstRow, lastRow; 932 double xform[4], inv_xform[4]; 933 double xmult, ymult; 934 int totalwidth = 0, totalchars = 0; 935#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \ 936 firstRow - opf->info.firstRow) * \ 937 (opf->info.lastCol - opf->info.firstCol + 1) + \ 938 (i)%(lastCol - firstCol + 1) + \ 939 firstCol - opf->info.firstCol) 940 941 *sWidth = 0; 942 943 opfi = &opf->info; 944 obitmapFont = (BitmapFontPtr) opf->fontPrivate; 945 946 bitmapFont = 0; 947 if (!(pf = CreateFontRec())) { 948 fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n", 949 (unsigned long)sizeof(FontRec)); 950 goto bail; 951 } 952 pf->refcnt = 0; 953 pf->bit = opf->bit; 954 pf->byte = opf->byte; 955 pf->glyph = opf->glyph; 956 pf->scan = opf->scan; 957 958 pf->get_glyphs = bitmapGetGlyphs; 959 pf->get_metrics = bitmapGetMetrics; 960 pf->unload_font = bitmapUnloadScalable; 961 pf->unload_glyphs = NULL; 962 963 pfi = &pf->info; 964 *pfi = *opfi; 965 /* If charset subsetting specified in vals, determine what our range 966 needs to be for the output font */ 967 if (vals->nranges) 968 { 969 int i; 970 971 pfi->allExist = 0; 972 firstCol = 255; 973 lastCol = 0; 974 firstRow = 255; 975 lastRow = 0; 976 977 for (i = 0; i < vals->nranges; i++) 978 { 979 if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high) 980 { 981 firstCol = opfi->firstCol; 982 lastCol = opfi->lastCol; 983 } 984 if (firstCol > vals->ranges[i].min_char_low) 985 firstCol = vals->ranges[i].min_char_low; 986 if (lastCol < vals->ranges[i].max_char_low) 987 lastCol = vals->ranges[i].max_char_low; 988 if (firstRow > vals->ranges[i].min_char_high) 989 firstRow = vals->ranges[i].min_char_high; 990 if (lastRow < vals->ranges[i].max_char_high) 991 lastRow = vals->ranges[i].max_char_high; 992 } 993 994 if (firstCol > lastCol || firstRow > lastRow) 995 goto bail; 996 997 if (firstCol < opfi->firstCol) 998 firstCol = opfi->firstCol; 999 if (lastCol > opfi->lastCol) 1000 lastCol = opfi->lastCol; 1001 if (firstRow < opfi->firstRow) 1002 firstRow = opfi->firstRow; 1003 if (lastRow > opfi->lastRow) 1004 lastRow = opfi->lastRow; 1005 } 1006 else 1007 { 1008 firstCol = opfi->firstCol; 1009 lastCol = opfi->lastCol; 1010 firstRow = opfi->firstRow; 1011 lastRow = opfi->lastRow; 1012 } 1013 1014 bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec)); 1015 if (!bitmapFont) { 1016 fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n", 1017 (unsigned long)sizeof(BitmapFontRec)); 1018 goto bail; 1019 } 1020 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 1021 pfi->firstRow = firstRow; 1022 pfi->lastRow = lastRow; 1023 pfi->firstCol = firstCol; 1024 pfi->lastCol = lastCol; 1025 pf->fontPrivate = (pointer) bitmapFont; 1026 bitmapFont->version_num = obitmapFont->version_num; 1027 bitmapFont->num_chars = nchars; 1028 bitmapFont->num_tables = obitmapFont->num_tables; 1029 bitmapFont->metrics = 0; 1030 bitmapFont->ink_metrics = 0; 1031 bitmapFont->bitmaps = 0; 1032 bitmapFont->encoding = 0; 1033 bitmapFont->bitmapExtra = 0; 1034 bitmapFont->pDefault = 0; 1035 bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec)); 1036 if (!bitmapFont->metrics) { 1037 fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n", 1038 nchars, (unsigned long)sizeof(CharInfoRec)); 1039 goto bail; 1040 } 1041 bitmapFont->encoding = 1042 (CharInfoPtr **) xcalloc(NUM_SEGMENTS(nchars), 1043 sizeof(CharInfoPtr*)); 1044 if (!bitmapFont->encoding) { 1045 fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n", 1046 nchars, (unsigned long)sizeof(CharInfoPtr)); 1047 goto bail; 1048 } 1049 1050#undef MAXSHORT 1051#define MAXSHORT 32767 1052#undef MINSHORT 1053#define MINSHORT -32768 1054 1055 pfi->anamorphic = FALSE; 1056 if (heightMult != widthMult) 1057 pfi->anamorphic = TRUE; 1058 pfi->cachable = TRUE; 1059 1060 if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 1061 inv_xform, &xmult, &ymult)) 1062 goto bail; 1063 1064 pfi->fontAscent = opfi->fontAscent * ymult; 1065 pfi->fontDescent = opfi->fontDescent * ymult; 1066 1067 pfi->minbounds.leftSideBearing = MAXSHORT; 1068 pfi->minbounds.rightSideBearing = MAXSHORT; 1069 pfi->minbounds.ascent = MAXSHORT; 1070 pfi->minbounds.descent = MAXSHORT; 1071 pfi->minbounds.characterWidth = MAXSHORT; 1072 pfi->minbounds.attributes = MAXSHORT; 1073 1074 pfi->maxbounds.leftSideBearing = MINSHORT; 1075 pfi->maxbounds.rightSideBearing = MINSHORT; 1076 pfi->maxbounds.ascent = MINSHORT; 1077 pfi->maxbounds.descent = MINSHORT; 1078 pfi->maxbounds.characterWidth = MINSHORT; 1079 pfi->maxbounds.attributes = MINSHORT; 1080 1081 /* Compute the transformation and inverse transformation matrices. 1082 Can fail if the determinant is zero. */ 1083 1084 pci = bitmapFont->metrics; 1085 for (i = 0; i < nchars; i++) 1086 { 1087 if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) 1088 { 1089 double newlsb, newrsb, newdesc, newasc, point[2]; 1090 1091#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) 1092#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) 1093 1094 if (vals->nranges) 1095 { 1096 int row = i / (lastCol - firstCol + 1) + firstRow; 1097 int col = i % (lastCol - firstCol + 1) + firstCol; 1098 int ch = (row << 8) + col; 1099 int j; 1100 for (j = 0; j < vals->nranges; j++) 1101 if (ch >= minchar(vals->ranges[j]) && 1102 ch <= maxchar(vals->ranges[j])) 1103 break; 1104 if (j == vals->nranges) 1105 { 1106 continue; 1107 } 1108 } 1109 1110 if (opci->metrics.leftSideBearing == 0 && 1111 opci->metrics.rightSideBearing == 0 && 1112 opci->metrics.ascent == 0 && 1113 opci->metrics.descent == 0 && 1114 opci->metrics.characterWidth == 0) 1115 { 1116 continue; 1117 } 1118 1119 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 1120 bitmapFont->encoding[SEGMENT_MAJOR(i)]= 1121 (CharInfoPtr*)xcalloc(BITMAP_FONT_SEGMENT_SIZE, 1122 sizeof(CharInfoPtr)); 1123 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) 1124 goto bail; 1125 } 1126 ACCESSENCODINGL(bitmapFont->encoding, i) = pci; 1127 1128 /* Compute new extents for this glyph */ 1129 TRANSFORM_POINT(xform, 1130 opci->metrics.leftSideBearing, 1131 -opci->metrics.descent, 1132 point); 1133 newlsb = point[0]; 1134 newrsb = newlsb; 1135 newdesc = -point[1]; 1136 newasc = -newdesc; 1137 TRANSFORM_POINT(xform, 1138 opci->metrics.leftSideBearing, 1139 opci->metrics.ascent, 1140 point); 1141 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 1142 TRANSFORM_POINT(xform, 1143 opci->metrics.rightSideBearing, 1144 -opci->metrics.descent, 1145 point); 1146 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 1147 TRANSFORM_POINT(xform, 1148 opci->metrics.rightSideBearing, 1149 opci->metrics.ascent, 1150 point); 1151 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 1152 1153 pci->metrics.leftSideBearing = (int)floor(newlsb); 1154 pci->metrics.rightSideBearing = (int)floor(newrsb + .5); 1155 pci->metrics.descent = (int)ceil(newdesc); 1156 pci->metrics.ascent = (int)floor(newasc + .5); 1157 /* Accumulate total width of characters before transformation, 1158 to ascertain predominant direction of font. */ 1159 totalwidth += opci->metrics.characterWidth; 1160 pci->metrics.characterWidth = 1161 doround((double)opci->metrics.characterWidth * xmult); 1162 pci->metrics.attributes = 1163 doround((double)opci->metrics.characterWidth * sWidthMult); 1164 if (!pci->metrics.characterWidth) 1165 { 1166 /* Since transformation may shrink width, height, and 1167 escapement to zero, make sure existing characters 1168 are not mistaken for undefined characters. */ 1169 1170 if (pci->metrics.rightSideBearing == 1171 pci->metrics.leftSideBearing) 1172 pci->metrics.rightSideBearing++; 1173 if (pci->metrics.ascent == -pci->metrics.descent) 1174 pci->metrics.ascent++; 1175 } 1176 1177 pci++; 1178 } 1179 } 1180 1181 1182 /* 1183 * For each character, set the per-character metrics, scale the glyph, and 1184 * check per-font minbounds and maxbounds character information. 1185 */ 1186 1187 pci = bitmapFont->metrics; 1188 for (i = 0; i < nchars; i++) 1189 { 1190 if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) && 1191 (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) 1192 { 1193 totalchars++; 1194 *sWidth += abs((int)(INT16)pci->metrics.attributes); 1195#define MINMAX(field) \ 1196 if (pfi->minbounds.field > pci->metrics.field) \ 1197 pfi->minbounds.field = pci->metrics.field; \ 1198 if (pfi->maxbounds.field < pci->metrics.field) \ 1199 pfi->maxbounds.field = pci->metrics.field 1200 1201 MINMAX(leftSideBearing); 1202 MINMAX(rightSideBearing); 1203 MINMAX(ascent); 1204 MINMAX(descent); 1205 MINMAX(characterWidth); 1206 1207 /* Hack: Cast attributes into a signed quantity. Tread lightly 1208 for now and don't go changing the global Xproto.h file */ 1209 if ((INT16)pfi->minbounds.attributes > 1210 (INT16)pci->metrics.attributes) 1211 pfi->minbounds.attributes = pci->metrics.attributes; 1212 if ((INT16)pfi->maxbounds.attributes < 1213 (INT16)pci->metrics.attributes) 1214 pfi->maxbounds.attributes = pci->metrics.attributes; 1215#undef MINMAX 1216 } 1217 } 1218 pfi->ink_minbounds = pfi->minbounds; 1219 pfi->ink_maxbounds = pfi->maxbounds; 1220 if (totalchars) 1221 { 1222 *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars; 1223 if (totalwidth < 0) 1224 { 1225 /* Dominant direction is R->L */ 1226 *sWidth = -*sWidth; 1227 } 1228 1229 if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth) 1230 vals->width = pfi->minbounds.characterWidth * 10; 1231 else 1232 vals->width = doround((double)*sWidth * vals->pixel_matrix[0] / 1233 1000.0); 1234 } 1235 else 1236 { 1237 vals->width = 0; 1238 *sWidth = 0; 1239 } 1240 FontComputeInfoAccelerators (pfi); 1241 1242 if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) { 1243 unsigned int r, 1244 c, 1245 cols; 1246 1247 r = pfi->defaultCh >> 8; 1248 c = pfi->defaultCh & 0xFF; 1249 if (pfi->firstRow <= r && r <= pfi->lastRow && 1250 pfi->firstCol <= c && c <= pfi->lastCol) { 1251 cols = pfi->lastCol - pfi->firstCol + 1; 1252 r = r - pfi->firstRow; 1253 c = c - pfi->firstCol; 1254 bitmapFont->pDefault = 1255 ACCESSENCODING(bitmapFont->encoding, r * cols + c); 1256 } 1257 } 1258 1259 *newWidthMult = xmult; 1260 *newHeightMult = ymult; 1261 return pf; 1262bail: 1263 if (pf) 1264 xfree(pf); 1265 if (bitmapFont) { 1266 xfree(bitmapFont->metrics); 1267 xfree(bitmapFont->ink_metrics); 1268 xfree(bitmapFont->bitmaps); 1269 if(bitmapFont->encoding) 1270 for(i=0; i<NUM_SEGMENTS(nchars); i++) 1271 xfree(bitmapFont->encoding[i]); 1272 xfree(bitmapFont->encoding); 1273 } 1274 return NULL; 1275} 1276 1277static void 1278ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci, 1279 double *inv_xform, double widthMult, double heightMult) 1280{ 1281 register char *bitmap, /* The bits */ 1282 *newBitmap; 1283 register int bpr, /* Padding information */ 1284 newBpr; 1285 int width, /* Extents information */ 1286 height, 1287 newWidth, 1288 newHeight; 1289 register int row, /* Loop variables */ 1290 col; 1291 INT32 deltaX, /* Increments for resampling loop */ 1292 deltaY; 1293 INT32 xValue, /* Subscripts for resampling loop */ 1294 yValue; 1295 double point[2]; 1296 unsigned char *char_grayscale = 0; 1297 INT32 *diffusion_workspace = NULL, *thisrow = NULL, 1298 *nextrow = NULL, pixmult = 0; 1299 int box_x = 0, box_y = 0; 1300 1301 static unsigned char masklsb[] = 1302 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; 1303 static unsigned char maskmsb[] = 1304 { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; 1305 unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb); 1306 1307 1308 bitmap = opci->bits; 1309 newBitmap = pci->bits; 1310 width = GLYPHWIDTHPIXELS(opci); 1311 height = GLYPHHEIGHTPIXELS(opci); 1312 newWidth = GLYPHWIDTHPIXELS(pci); 1313 newHeight = GLYPHHEIGHTPIXELS(pci); 1314 if (!newWidth || !newHeight || !width || !height) 1315 return; 1316 1317 bpr = BYTES_PER_ROW(width, pFont->glyph); 1318 newBpr = BYTES_PER_ROW(newWidth, pFont->glyph); 1319 1320 if (widthMult > 0.0 && heightMult > 0.0 && 1321 (widthMult < 1.0 || heightMult < 1.0)) 1322 { 1323 /* We are reducing in one or both dimensions. In an attempt to 1324 reduce aliasing, we'll antialias by passing the original 1325 glyph through a low-pass box filter (which results in a 1326 grayscale image), then use error diffusion to create bitonal 1327 output in the resampling loop. */ 1328 1329 /* First compute the sizes of the box filter */ 1330 widthMult = ceil(1.0 / widthMult); 1331 heightMult = ceil(1.0 / heightMult); 1332 box_x = width / 2; 1333 box_y = height / 2; 1334 if (widthMult < (double)box_x) box_x = (int)widthMult; 1335 if (heightMult < (double)box_y) box_y = (int)heightMult; 1336 /* The pixmult value (below) is used to darken the image before 1337 we perform error diffusion: a necessary concession to the 1338 fact that it's very difficult to generate readable halftoned 1339 glyphs. The degree of darkening is proportional to the size 1340 of the blurring filter, hence inversely proportional to the 1341 darkness of the lightest gray that results from antialiasing. 1342 The result is that characters that exercise this logic (those 1343 generated by reducing from a larger source font) tend to err 1344 on the side of being too bold instead of being too light to 1345 be readable. */ 1346 pixmult = box_x * box_y * 192; 1347 1348 if (box_x > 1 || box_y > 1) 1349 { 1350 /* Looks like we need to anti-alias. Create a workspace to 1351 contain the grayscale character plus an additional row and 1352 column for scratch */ 1353 char_grayscale = 1354 (unsigned char *)xalloc((width + 1) * (height + 1)); 1355 if (char_grayscale) 1356 { 1357 diffusion_workspace = 1358 (INT32 *)xalloc((newWidth + 2) * 2 * sizeof(int)); 1359 if (!diffusion_workspace) 1360 { 1361 fprintf(stderr, "Warning: Couldn't allocate diffusion" 1362 " workspace (%ld)\n", 1363 (newWidth + 2) * 2 * (unsigned long)sizeof(int)); 1364 xfree(char_grayscale); 1365 char_grayscale = (unsigned char *)0; 1366 } 1367 /* Initialize our error diffusion workspace for later use */ 1368 bzero((char *)diffusion_workspace + sizeof(INT32), 1369 (newWidth + 3) * sizeof(int)); 1370 thisrow = diffusion_workspace + 1; 1371 nextrow = diffusion_workspace + newWidth + 3; 1372 } else { 1373 fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1)); 1374 } 1375 } 1376 } 1377 1378 if (char_grayscale) 1379 { 1380 /* We will be doing antialiasing. First copy the bitmap into 1381 our buffer, mapping input range [0,1] to output range 1382 [0,255]. */ 1383 register unsigned char *srcptr, *dstptr; 1384 srcptr = (unsigned char *)bitmap; 1385 dstptr = char_grayscale; 1386 for (row = 0; row < height; row++) 1387 { 1388 for (col = 0; col < width; col++) 1389 *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0; 1390 srcptr += bpr; /* On to next row of source */ 1391 dstptr++; /* Skip scratch column in dest */ 1392 } 1393 if (box_x > 1) 1394 { 1395 /* Our box filter has a width > 1... let's filter the rows */ 1396 1397 int right_width = box_x / 2; 1398 int left_width = box_x - right_width - 1; 1399 1400 for (row = 0; row < height; row++) 1401 { 1402 int sum = 0; 1403 int left_size = 0, right_size = 0; 1404 1405 srcptr = char_grayscale + (width + 1) * row; 1406 dstptr = char_grayscale + (width + 1) * height; /* scratch */ 1407 1408 /* We've computed the shape of our full box filter. Now 1409 compute the right-hand part of the moving sum */ 1410 for (right_size = 0; right_size < right_width; right_size++) 1411 sum += srcptr[right_size]; 1412 1413 /* Now start moving the sum, growing the box filter, and 1414 dropping averages into our scratch buffer */ 1415 for (left_size = 0; left_size < left_width; left_size++) 1416 { 1417 sum += srcptr[right_width]; 1418 *dstptr++ = sum / (left_size + right_width + 1); 1419 srcptr++; 1420 } 1421 1422 /* The box filter has reached full width... continue 1423 computation of moving average until the right side 1424 hits the wall. */ 1425 for (col = left_size; col + right_size < width; col++) 1426 { 1427 sum += srcptr[right_width]; 1428 *dstptr++ = sum / box_x; 1429 sum -= srcptr[-left_width]; 1430 srcptr++; 1431 } 1432 1433 /* Collapse the right side of the box filter */ 1434 for (; right_size > 0; right_size--) 1435 { 1436 *dstptr++ = sum / (left_width + right_size); 1437 sum -= srcptr[-left_width]; 1438 srcptr++; 1439 } 1440 1441 /* Done with the row... copy dest back over source */ 1442 memmove(char_grayscale + (width + 1) * row, 1443 char_grayscale + (width + 1) * height, 1444 width); 1445 } 1446 } 1447 if (box_y > 1) 1448 { 1449 /* Our box filter has a height > 1... let's filter the columns */ 1450 1451 int bottom_height = box_y / 2; 1452 int top_height = box_y - bottom_height - 1; 1453 1454 for (col = 0; col < width; col++) 1455 { 1456 int sum = 0; 1457 int top_size = 0, bottom_size = 0; 1458 1459 srcptr = char_grayscale + col; 1460 dstptr = char_grayscale + width; /* scratch */ 1461 1462 /* We've computed the shape of our full box filter. Now 1463 compute the bottom part of the moving sum */ 1464 for (bottom_size = 0; 1465 bottom_size < bottom_height; 1466 bottom_size++) 1467 sum += srcptr[bottom_size * (width + 1)]; 1468 1469 /* Now start moving the sum, growing the box filter, and 1470 dropping averages into our scratch buffer */ 1471 for (top_size = 0; top_size < top_height; top_size++) 1472 { 1473 sum += srcptr[bottom_height * (width + 1)]; 1474 *dstptr = sum / (top_size + bottom_height + 1); 1475 dstptr += width + 1; 1476 srcptr += width + 1; 1477 } 1478 1479 /* The box filter has reached full height... continue 1480 computation of moving average until the bottom 1481 hits the wall. */ 1482 for (row = top_size; row + bottom_size < height; row++) 1483 { 1484 sum += srcptr[bottom_height * (width + 1)]; 1485 *dstptr = sum / box_y; 1486 dstptr += width + 1; 1487 sum -= srcptr[-top_height * (width + 1)]; 1488 srcptr += width + 1; 1489 } 1490 1491 /* Collapse the bottom of the box filter */ 1492 for (; bottom_size > 0; bottom_size--) 1493 { 1494 *dstptr = sum / (top_height + bottom_size); 1495 dstptr += width + 1; 1496 sum -= srcptr[-top_height * (width + 1)]; 1497 srcptr += width + 1; 1498 } 1499 1500 /* Done with the column... copy dest back over source */ 1501 1502 dstptr = char_grayscale + col; 1503 srcptr = char_grayscale + width; /* scratch */ 1504 for (row = 0; row < height; row++) 1505 { 1506 *dstptr = *srcptr; 1507 dstptr += width + 1; 1508 srcptr += width + 1; 1509 } 1510 } 1511 } 1512 1513 /* Increase the grayvalue to increase ink a bit */ 1514 srcptr = char_grayscale; 1515 for (row = 0; row < height; row++) 1516 { 1517 for (col = 0; col < width; col++) 1518 { 1519 register int pixvalue = (int)*srcptr * pixmult / 256; 1520 if (pixvalue > 255) pixvalue = 255; 1521 *srcptr = pixvalue; 1522 srcptr++; 1523 } 1524 srcptr++; 1525 } 1526 } 1527 1528 /* Compute the increment values for the resampling loop */ 1529 TRANSFORM_POINT(inv_xform, 1, 0, point); 1530 deltaX = (INT32)(point[0] * 65536.0); 1531 deltaY = (INT32)(-point[1] * 65536.0); 1532 1533 /* Resampling loop: resamples original glyph for generation of new 1534 glyph in transformed coordinate system. */ 1535 1536 for (row = 0; row < newHeight; row++) 1537 { 1538 /* Compute inverse transformation for start of this row */ 1539 TRANSFORM_POINT(inv_xform, 1540 (double)(pci->metrics.leftSideBearing) + .5, 1541 (double)(pci->metrics.ascent - row) - .5, 1542 point); 1543 1544 /* Adjust for coordinate system to get resampling point */ 1545 point[0] -= opci->metrics.leftSideBearing; 1546 point[1] = opci->metrics.ascent - point[1]; 1547 1548 /* Convert to integer coordinates */ 1549 xValue = (INT32)(point[0] * 65536.0); 1550 yValue = (INT32)(point[1] * 65536.0); 1551 1552 if (char_grayscale) 1553 { 1554 INT32 *temp; 1555 for (col = 0; col < newWidth; col++) 1556 { 1557 register int x = xValue >> 16, y = yValue >> 16; 1558 int pixvalue, error; 1559 1560 pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ? 1561 char_grayscale[x + y * (width + 1)] : 0) + 1562 thisrow[col] / 16; 1563 if (pixvalue > 255) pixvalue = 255; 1564 else if (pixvalue < 0) pixvalue = 0; 1565 1566 /* Choose the bit value and set resulting error value */ 1567 if (pixvalue >= 128) 1568 { 1569 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; 1570 error = pixvalue - 255; 1571 } 1572 else 1573 error = -pixvalue; 1574 1575 /* Diffuse the error */ 1576 thisrow[col + 1] += error * 7; 1577 nextrow[col - 1] += error * 3; 1578 nextrow[col] += error * 5; 1579 nextrow[col + 1] = error; 1580 1581 xValue += deltaX; 1582 yValue += deltaY; 1583 } 1584 1585 /* Add in error values that fell off either end */ 1586 nextrow[0] += nextrow[-1]; 1587 nextrow[newWidth - 2] += thisrow[newWidth]; 1588 nextrow[newWidth - 1] += nextrow[newWidth]; 1589 nextrow[newWidth] = 0; 1590 1591 temp = nextrow; 1592 nextrow = thisrow; 1593 thisrow = temp; 1594 nextrow[-1] = nextrow[0] = 0; 1595 } 1596 else 1597 { 1598 for (col = 0; col < newWidth; col++) 1599 { 1600 register int x = xValue >> 16, y = yValue >> 16; 1601 1602 if (x >= 0 && x < width && y >= 0 && y < height) 1603 { 1604 /* Use point-sampling for rescaling. */ 1605 1606 if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7]) 1607 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; 1608 } 1609 1610 xValue += deltaX; 1611 yValue += deltaY; 1612 } 1613 } 1614 } 1615 1616 1617 if (char_grayscale) 1618 { 1619 xfree(char_grayscale); 1620 xfree(diffusion_workspace); 1621 } 1622} 1623 1624static FontPtr 1625BitmapScaleBitmaps(FontPtr pf, /* scaled font */ 1626 FontPtr opf, /* originating font */ 1627 double widthMult, /* glyphs width scale factor */ 1628 double heightMult, /* glyphs height scale factor */ 1629 FontScalablePtr vals) 1630{ 1631 register int i; 1632 int nchars = 0; 1633 char *glyphBytes; 1634 BitmapFontPtr bitmapFont, 1635 obitmapFont; 1636 CharInfoPtr pci, 1637 opci; 1638 FontInfoPtr pfi; 1639 int glyph; 1640 unsigned bytestoalloc = 0; 1641 int firstCol, lastCol, firstRow, lastRow; 1642 1643 double xform[4], inv_xform[4]; 1644 double xmult, ymult; 1645 1646 bitmapFont = (BitmapFontPtr) pf->fontPrivate; 1647 obitmapFont = (BitmapFontPtr) opf->fontPrivate; 1648 1649 if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 1650 inv_xform, &xmult, &ymult)) 1651 goto bail; 1652 1653 pfi = &pf->info; 1654 firstCol = pfi->firstCol; 1655 lastCol = pfi->lastCol; 1656 firstRow = pfi->firstRow; 1657 lastRow = pfi->lastRow; 1658 1659 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 1660 glyph = pf->glyph; 1661 for (i = 0; i < nchars; i++) 1662 { 1663 if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) 1664 bytestoalloc += BYTES_FOR_GLYPH(pci, glyph); 1665 } 1666 1667 /* Do we add the font malloc stuff for VALUE ADDED ? */ 1668 /* Will need to remember to free in the Unload routine */ 1669 1670 1671 bitmapFont->bitmaps = (char *) xalloc(bytestoalloc); 1672 if (!bitmapFont->bitmaps) { 1673 fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); 1674 goto bail; 1675 } 1676 bzero(bitmapFont->bitmaps, bytestoalloc); 1677 1678 glyphBytes = bitmapFont->bitmaps; 1679 for (i = 0; i < nchars; i++) 1680 { 1681 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && 1682 (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) 1683 { 1684 pci->bits = glyphBytes; 1685 ScaleBitmap (pf, opci, pci, inv_xform, 1686 widthMult, heightMult); 1687 glyphBytes += BYTES_FOR_GLYPH(pci, glyph); 1688 } 1689 } 1690 return pf; 1691 1692bail: 1693 if (pf) 1694 xfree(pf); 1695 if (bitmapFont) { 1696 xfree(bitmapFont->metrics); 1697 xfree(bitmapFont->ink_metrics); 1698 xfree(bitmapFont->bitmaps); 1699 if(bitmapFont->encoding) 1700 for(i=0; i<NUM_SEGMENTS(nchars); i++) 1701 xfree(bitmapFont->encoding[i]); 1702 xfree(bitmapFont->encoding); 1703 } 1704 return NULL; 1705} 1706 1707static FontPtr 1708PrinterScaleBitmaps(FontPtr pf, /* scaled font */ 1709 FontPtr opf, /* originating font */ 1710 double widthMult, /* glyphs width scale factor */ 1711 double heightMult, /* glyphs height scale factor */ 1712 FontScalablePtr vals) 1713{ 1714 register int i; 1715 int nchars = 0; 1716 char *glyphBytes; 1717 BitmapFontPtr bitmapFont, 1718 obitmapFont; 1719 CharInfoPtr pci; 1720 FontInfoPtr pfi; 1721 int glyph; 1722 unsigned bytestoalloc = 0; 1723 int firstCol, lastCol, firstRow, lastRow; 1724 1725 double xform[4], inv_xform[4]; 1726 double xmult, ymult; 1727 1728 bitmapFont = (BitmapFontPtr) pf->fontPrivate; 1729 obitmapFont = (BitmapFontPtr) opf->fontPrivate; 1730 1731 if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 1732 inv_xform, &xmult, &ymult)) 1733 goto bail; 1734 1735 pfi = &pf->info; 1736 firstCol = pfi->firstCol; 1737 lastCol = pfi->lastCol; 1738 firstRow = pfi->firstRow; 1739 lastRow = pfi->lastRow; 1740 1741 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 1742 glyph = pf->glyph; 1743 for (i = 0; i < nchars; i++) 1744 { 1745 if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) 1746 bytestoalloc = MAX(bytestoalloc,BYTES_FOR_GLYPH(pci, glyph)); 1747 } 1748 1749 /* Do we add the font malloc stuff for VALUE ADDED ? */ 1750 /* Will need to remember to free in the Unload routine */ 1751 1752 1753 bitmapFont->bitmaps = (char *) xalloc(bytestoalloc); 1754 if (!bitmapFont->bitmaps) { 1755 fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); 1756 goto bail; 1757 } 1758 bzero(bitmapFont->bitmaps, bytestoalloc); 1759 1760 glyphBytes = bitmapFont->bitmaps; 1761 for (i = 0; i < nchars; i++) 1762 { 1763 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && 1764 (ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) 1765 { 1766 pci->bits = glyphBytes; 1767 } 1768 } 1769 return pf; 1770 1771bail: 1772 if (pf) 1773 xfree(pf); 1774 if (bitmapFont) { 1775 xfree(bitmapFont->metrics); 1776 xfree(bitmapFont->ink_metrics); 1777 xfree(bitmapFont->bitmaps); 1778 if(bitmapFont->encoding) 1779 for(i=0; i<NUM_SEGMENTS(nchars); i++) 1780 xfree(bitmapFont->encoding[i]); 1781 xfree(bitmapFont->encoding); 1782 } 1783 return NULL; 1784} 1785 1786#ifdef NOTDEF 1787/* 1788 * exported interfaces 1789 */ 1790 1791FontFileLoadName(FontFileDirPtr *dirs, int ndirs, char *name, FontPtr *pfont, 1792 fsBitmapFormat format, fsBitmapFormatMask fmask) 1793{ 1794 FontFileNamePtr fname; 1795 char full_name[1024]; 1796 int ret = BadFontName; 1797 int i; 1798 1799 i = 0; 1800 while (i < ndirs) { 1801 if (fname = FontFileFindNameInDir(dirs[i], name)) { 1802 if (!fname->alias) { 1803 if (!fname->font) { 1804 strcpy(full_name, dirs[i]->dir); 1805 strcat(full_name, fname->file); 1806 ret = FontFileLoad(pfont, full_name, format, fmask); 1807 if (ret == Successful) { 1808 fname->font = *pfont; 1809 (*pfont)->fpePrivate = (pointer) fname; 1810 } 1811 return ret; 1812 } 1813 *pfont = fname->font; 1814 return Successful; 1815 } 1816 name = fname->file; 1817 i = 0; 1818 } else 1819 i++; 1820 } 1821 return BadFontName; 1822} 1823#endif 1824 1825/* ARGSUSED */ 1826int 1827BitmapOpenScalable (FontPathElementPtr fpe, 1828 FontPtr *pFont, 1829 int flags, 1830 FontEntryPtr entry, 1831 char *fileName, /* unused */ 1832 FontScalablePtr vals, 1833 fsBitmapFormat format, 1834 fsBitmapFormatMask fmask, 1835 FontPtr non_cachable_font) /* We don't do licensing */ 1836{ 1837 FontScalableRec best; 1838 FontPtr font = NullFont; 1839 double dx, sdx, 1840 dy, sdy, 1841 savedX, savedY; 1842 FontPropPtr props; 1843 char *isStringProp = NULL; 1844 int propCount; 1845 int status; 1846 long sWidth; 1847 1848 FontEntryPtr scaleFrom; 1849 FontPathElementPtr scaleFPE; 1850 FontPtr sourceFont; 1851 char fontName[MAXFONTNAMELEN]; 1852 1853 /* Can't deal with mix-endian fonts yet */ 1854 1855#ifdef NOTDEF /* XXX need better test */ 1856 if ((format & BitmapFormatByteOrderMask) != 1857 (format & BitmapFormatBitOrderMask)) 1858 return NullFontFileName; 1859#endif 1860 1861 /* Reject outrageously small font sizes to keep the math from 1862 blowing up. */ 1863 if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 || 1864 get_matrix_horizontal_component(vals->pixel_matrix) < 1.0) 1865 return BadFontName; 1866 1867 scaleFrom = (*find_scale[BitmapGetRenderIndex(entry->u.bitmap.renderer)]) 1868 (fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, &scaleFPE); 1869 1870 if (!scaleFrom) 1871 return BadFontName; 1872 1873 status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, 1874 format, fmask); 1875 1876 if (status != Successful) 1877 return BadFontName; 1878 1879 if (!vals->width) 1880 vals->width = best.width * dx; 1881 1882 /* Compute the scaled font */ 1883 1884 savedX = dx; 1885 savedY = dy; 1886 font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth); 1887 if (font) 1888 font = (*scale[ BitmapGetRenderIndex(entry->u.bitmap.renderer) ]) 1889 (font, sourceFont, savedX, savedY, vals); 1890 1891 if (!font) 1892 { 1893 if (!sourceFont->refcnt) 1894 FontFileCloseFont((FontPathElementPtr) 0, sourceFont); 1895 return AllocError; 1896 } 1897 1898 /* Prepare font properties for the new font */ 1899 1900 strcpy (fontName, scaleFrom->name.name); 1901 FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); 1902 1903 propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, 1904 dx, dy, sdx, sdy, sWidth, &props, 1905 &isStringProp); 1906 1907 if (!sourceFont->refcnt) 1908 FontFileCloseFont((FontPathElementPtr) 0, sourceFont); 1909 1910 if (propCount && (!props || !isStringProp)) 1911 { 1912 font->info.nprops = 0; 1913 font->info.props = (FontPropPtr)0; 1914 font->info.isStringProp = (char *)0; 1915 bitmapUnloadScalable(font); 1916 return AllocError; 1917 } 1918 1919 font->info.props = props; 1920 font->info.nprops = propCount; 1921 font->info.isStringProp = isStringProp; 1922 1923 *pFont = font; 1924 return Successful; 1925} 1926 1927int 1928BitmapGetInfoScalable (FontPathElementPtr fpe, 1929 FontInfoPtr pFontInfo, 1930 FontEntryPtr entry, 1931 FontNamePtr fontName, 1932 char *fileName, 1933 FontScalablePtr vals) 1934{ 1935 FontPtr pfont; 1936 int flags = 0; 1937 long format = 0; /* It doesn't matter what format for just info */ 1938 long fmask = 0; 1939 int ret; 1940 1941 ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals, 1942 format, fmask, NULL); 1943 if (ret != Successful) 1944 return ret; 1945 *pFontInfo = pfont->info; 1946 1947 pfont->info.nprops = 0; 1948 pfont->info.props = NULL; 1949 pfont->info.isStringProp = NULL; 1950 1951 (*pfont->unload_font)(pfont); 1952 return Successful; 1953} 1954 1955static void 1956bitmapUnloadScalable (FontPtr pFont) 1957{ 1958 BitmapFontPtr bitmapFont; 1959 FontInfoPtr pfi; 1960 int i, nencoding; 1961 1962 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 1963 pfi = &pFont->info; 1964 xfree (pfi->props); 1965 xfree (pfi->isStringProp); 1966 if(bitmapFont->encoding) { 1967 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 1968 (pFont->info.lastRow - pFont->info.firstRow + 1); 1969 for(i=0; i<NUM_SEGMENTS(nencoding); i++) 1970 xfree(bitmapFont->encoding[i]); 1971 } 1972 xfree (bitmapFont->encoding); 1973 xfree (bitmapFont->bitmaps); 1974 xfree (bitmapFont->ink_metrics); 1975 xfree (bitmapFont->metrics); 1976 xfree (pFont->fontPrivate); 1977 DestroyFontRec (pFont); 1978} 1979