1/* 2 3Copyright 1990, 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 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29/* 30 * Author: Keith Packard, MIT X Consortium 31 */ 32 33#ifdef HAVE_CONFIG_H 34#include <config.h> 35#endif 36#include "libxfontint.h" 37#include "src/util/replace.h" 38 39#include <X11/fonts/fntfilst.h> 40#include <X11/fonts/bitmap.h> 41#include <X11/fonts/pcf.h> 42 43#ifndef MAX 44#define MAX(a,b) (((a)>(b)) ? a : b) 45#endif 46 47#include <stdarg.h> 48#include <stdint.h> 49#include <string.h> 50 51void 52pcfError(const char* message, ...) 53{ 54 va_list args; 55 56 va_start(args, message); 57 58 fprintf(stderr, "PCF Error: "); 59 vfprintf(stderr, message, args); 60 va_end(args); 61} 62 63/* Read PCF font files */ 64 65static void pcfUnloadFont ( FontPtr pFont ); 66static int position; 67 68 69#define IS_EOF(file) ((file)->eof == BUFFILEEOF) 70 71#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF) 72 73static int 74pcfGetLSB32(FontFilePtr file) 75{ 76 int c; 77 78 c = FontFileGetc(file); 79 c |= FontFileGetc(file) << 8; 80 c |= FontFileGetc(file) << 16; 81 c |= FontFileGetc(file) << 24; 82 position += 4; 83 return c; 84} 85 86static int 87pcfGetINT32(FontFilePtr file, CARD32 format) 88{ 89 int c; 90 91 if (PCF_BYTE_ORDER(format) == MSBFirst) { 92 c = FontFileGetc(file) << 24; 93 c |= FontFileGetc(file) << 16; 94 c |= FontFileGetc(file) << 8; 95 c |= FontFileGetc(file); 96 } else { 97 c = FontFileGetc(file); 98 c |= FontFileGetc(file) << 8; 99 c |= FontFileGetc(file) << 16; 100 c |= FontFileGetc(file) << 24; 101 } 102 position += 4; 103 return c; 104} 105 106static int 107pcfGetINT16(FontFilePtr file, CARD32 format) 108{ 109 int c; 110 111 if (PCF_BYTE_ORDER(format) == MSBFirst) { 112 c = FontFileGetc(file) << 8; 113 c |= FontFileGetc(file); 114 } else { 115 c = FontFileGetc(file); 116 c |= FontFileGetc(file) << 8; 117 } 118 position += 2; 119 return c; 120} 121 122#define pcfGetINT8(file, format) (position++, FontFileGetc(file)) 123 124static PCFTablePtr 125pcfReadTOC(FontFilePtr file, int *countp) 126{ 127 CARD32 version; 128 PCFTablePtr tables; 129 int count; 130 int i; 131 132 position = 0; 133 version = pcfGetLSB32(file); 134 if (version != PCF_FILE_VERSION) 135 return (PCFTablePtr) NULL; 136 count = pcfGetLSB32(file); 137 if (IS_EOF(file)) return (PCFTablePtr) NULL; 138 if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) { 139 pcfError("pcfReadTOC(): invalid file format\n"); 140 return NULL; 141 } 142 tables = mallocarray(count, sizeof(PCFTableRec)); 143 if (!tables) { 144 pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", 145 count, (int) sizeof(PCFTableRec)); 146 return (PCFTablePtr) NULL; 147 } 148 for (i = 0; i < count; i++) { 149 tables[i].type = pcfGetLSB32(file); 150 tables[i].format = pcfGetLSB32(file); 151 tables[i].size = pcfGetLSB32(file); 152 tables[i].offset = pcfGetLSB32(file); 153 if (IS_EOF(file)) goto Bail; 154 } 155 156 *countp = count; 157 return tables; 158 159 Bail: 160 free(tables); 161 return (PCFTablePtr) NULL; 162} 163 164/* 165 * PCF supports two formats for metrics, both the regular 166 * jumbo size, and 'lite' metrics, which are useful 167 * for most fonts which have even vaguely reasonable 168 * metrics 169 */ 170 171static Bool 172pcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 173{ 174 metric->leftSideBearing = pcfGetINT16(file, format); 175 metric->rightSideBearing = pcfGetINT16(file, format); 176 metric->characterWidth = pcfGetINT16(file, format); 177 metric->ascent = pcfGetINT16(file, format); 178 metric->descent = pcfGetINT16(file, format); 179 metric->attributes = pcfGetINT16(file, format); 180 if (IS_EOF(file)) return FALSE; 181 182 return TRUE; 183} 184 185static Bool 186pcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 187{ 188 metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; 189 metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; 190 metric->characterWidth = pcfGetINT8(file, format) - 0x80; 191 metric->ascent = pcfGetINT8(file, format) - 0x80; 192 metric->descent = pcfGetINT8(file, format) - 0x80; 193 metric->attributes = 0; 194 if (IS_EOF(file)) return FALSE; 195 196 return TRUE; 197} 198 199/* 200 * Position the file to the beginning of the specified table 201 * in the font file 202 */ 203static Bool 204pcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, 205 CARD32 type, CARD32 *formatp, CARD32 *sizep) 206{ 207 int i; 208 209 for (i = 0; i < ntables; i++) 210 if (tables[i].type == type) { 211 if (position > tables[i].offset) 212 return FALSE; 213 if (!FontFileSkip(file, tables[i].offset - position)) 214 return FALSE; 215 position = tables[i].offset; 216 *sizep = tables[i].size; 217 *formatp = tables[i].format; 218 return TRUE; 219 } 220 return FALSE; 221} 222 223static Bool 224pcfHasType (PCFTablePtr tables, int ntables, CARD32 type) 225{ 226 int i; 227 228 for (i = 0; i < ntables; i++) 229 if (tables[i].type == type) 230 return TRUE; 231 return FALSE; 232} 233 234/* 235 * pcfGetProperties 236 * 237 * Reads the font properties from the font file, filling in the FontInfo rec 238 * supplied. Used by by both ReadFont and ReadFontInfo routines. 239 */ 240 241static Bool 242pcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, 243 PCFTablePtr tables, int ntables) 244{ 245 FontPropPtr props = 0; 246 int nprops; 247 char *isStringProp = 0; 248 CARD32 format; 249 int i; 250 CARD32 size; 251 int string_size; 252 char *strings; 253 254 /* font properties */ 255 256 if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) 257 goto Bail; 258 format = pcfGetLSB32(file); 259 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 260 goto Bail; 261 nprops = pcfGetINT32(file, format); 262 if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { 263 pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); 264 goto Bail; 265 } 266 if (IS_EOF(file)) goto Bail; 267 props = mallocarray(nprops, sizeof(FontPropRec)); 268 if (!props) { 269 pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", 270 nprops, (int) sizeof(FontPropRec)); 271 goto Bail; 272 } 273 isStringProp = mallocarray(nprops, sizeof(char)); 274 if (!isStringProp) { 275 pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", 276 nprops, (int) sizeof(char)); 277 goto Bail; 278 } 279 for (i = 0; i < nprops; i++) { 280 props[i].name = pcfGetINT32(file, format); 281 isStringProp[i] = pcfGetINT8(file, format); 282 props[i].value = pcfGetINT32(file, format); 283 if (props[i].name < 0 284 || (isStringProp[i] != 0 && isStringProp[i] != 1) 285 || (isStringProp[i] && props[i].value < 0)) { 286 pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n", 287 props[i].name, isStringProp[i], props[i].value); 288 goto Bail; 289 } 290 if (IS_EOF(file)) goto Bail; 291 } 292 /* pad the property array */ 293 /* 294 * clever here - nprops is the same as the number of odd-units read, as 295 * only isStringProp are odd length 296 */ 297 if (nprops & 3) 298 { 299 i = 4 - (nprops & 3); 300 (void)FontFileSkip(file, i); 301 position += i; 302 } 303 if (IS_EOF(file)) goto Bail; 304 string_size = pcfGetINT32(file, format); 305 if (string_size < 0) goto Bail; 306 if (IS_EOF(file)) goto Bail; 307 strings = malloc(string_size); 308 if (!strings) { 309 pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); 310 goto Bail; 311 } 312 FontFileRead(file, strings, string_size); 313 if (IS_EOF(file)) goto Bail; 314 position += string_size; 315 for (i = 0; i < nprops; i++) { 316 if (props[i].name >= string_size) { 317 pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].name, string_size); 318 goto Bail; 319 } 320 props[i].name = MakeAtom(strings + props[i].name, 321 strnlen(strings + props[i].name, string_size - props[i].name), TRUE); 322 if (isStringProp[i]) { 323 if (props[i].value >= string_size) { 324 pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].value, string_size); 325 goto Bail; 326 } 327 props[i].value = MakeAtom(strings + props[i].value, 328 strnlen(strings + props[i].value, string_size - props[i].value), TRUE); 329 } 330 } 331 free(strings); 332 pFontInfo->isStringProp = isStringProp; 333 pFontInfo->props = props; 334 pFontInfo->nprops = nprops; 335 return TRUE; 336Bail: 337 free(isStringProp); 338 free(props); 339 return FALSE; 340} 341 342 343/* 344 * pcfReadAccel 345 * 346 * Fill in the accelerator information from the font file; used 347 * to read both BDF_ACCELERATORS and old style ACCELERATORS 348 */ 349 350static Bool 351pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, 352 PCFTablePtr tables, int ntables, CARD32 type) 353{ 354 CARD32 format; 355 CARD32 size; 356 357 if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || 358 IS_EOF(file)) 359 goto Bail; 360 format = pcfGetLSB32(file); 361 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 362 !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 363 { 364 goto Bail; 365 } 366 pFontInfo->noOverlap = pcfGetINT8(file, format); 367 pFontInfo->constantMetrics = pcfGetINT8(file, format); 368 pFontInfo->terminalFont = pcfGetINT8(file, format); 369 pFontInfo->constantWidth = pcfGetINT8(file, format); 370 pFontInfo->inkInside = pcfGetINT8(file, format); 371 pFontInfo->inkMetrics = pcfGetINT8(file, format); 372 pFontInfo->drawDirection = pcfGetINT8(file, format); 373 pFontInfo->anamorphic = FALSE; 374 pFontInfo->cachable = TRUE; 375 /* natural alignment */ pcfGetINT8(file, format); 376 pFontInfo->fontAscent = pcfGetINT32(file, format); 377 pFontInfo->fontDescent = pcfGetINT32(file, format); 378 pFontInfo->maxOverlap = pcfGetINT32(file, format); 379 if (IS_EOF(file)) goto Bail; 380 if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) 381 goto Bail; 382 if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) 383 goto Bail; 384 if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { 385 if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) 386 goto Bail; 387 if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) 388 goto Bail; 389 } else { 390 pFontInfo->ink_minbounds = pFontInfo->minbounds; 391 pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 392 } 393 return TRUE; 394Bail: 395 return FALSE; 396} 397 398int 399pcfReadFont(FontPtr pFont, FontFilePtr file, 400 int bit, int byte, int glyph, int scan) 401{ 402 CARD32 format; 403 CARD32 size; 404 BitmapFontPtr bitmapFont = 0; 405 int i; 406 PCFTablePtr tables = 0; 407 int ntables; 408 int nmetrics; 409 int nbitmaps; 410 int sizebitmaps; 411 int nink_metrics; 412 CharInfoPtr metrics = 0; 413 xCharInfo *ink_metrics = 0; 414 char *bitmaps = 0; 415 CharInfoPtr **encoding = 0; 416 int nencoding = 0; 417 int encodingOffset; 418 CARD32 bitmapSizes[GLYPHPADOPTIONS]; 419 CARD32 *offsets = 0; 420 Bool hasBDFAccelerators; 421 422 pFont->info.nprops = 0; 423 pFont->info.props = 0; 424 pFont->info.isStringProp=0; 425 426 if (!(tables = pcfReadTOC(file, &ntables))) 427 goto Bail; 428 429 /* properties */ 430 431 if (!pcfGetProperties(&pFont->info, file, tables, ntables)) 432 goto Bail; 433 434 /* Use the old accelerators if no BDF accelerators are in the file */ 435 436 hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 437 if (!hasBDFAccelerators) 438 if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) 439 goto Bail; 440 441 /* metrics */ 442 443 if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { 444 goto Bail; 445 } 446 format = pcfGetLSB32(file); 447 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 448 !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 449 goto Bail; 450 } 451 if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 452 nmetrics = pcfGetINT32(file, format); 453 else 454 nmetrics = pcfGetINT16(file, format); 455 if (IS_EOF(file)) goto Bail; 456 if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { 457 pcfError("pcfReadFont(): invalid file format\n"); 458 goto Bail; 459 } 460 metrics = mallocarray(nmetrics, sizeof(CharInfoRec)); 461 if (!metrics) { 462 pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", 463 nmetrics, (int) sizeof(CharInfoRec)); 464 goto Bail; 465 } 466 for (i = 0; i < nmetrics; i++) 467 if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 468 if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) 469 goto Bail; 470 } else { 471 if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) 472 goto Bail; 473 } 474 475 /* bitmaps */ 476 477 if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) 478 goto Bail; 479 format = pcfGetLSB32(file); 480 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 481 goto Bail; 482 483 nbitmaps = pcfGetINT32(file, format); 484 if (nbitmaps != nmetrics || IS_EOF(file)) 485 goto Bail; 486 /* nmetrics is already ok, so nbitmap also is */ 487 offsets = mallocarray(nbitmaps, sizeof(CARD32)); 488 if (!offsets) { 489 pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", 490 nbitmaps, (int) sizeof(CARD32)); 491 goto Bail; 492 } 493 for (i = 0; i < nbitmaps; i++) { 494 offsets[i] = pcfGetINT32(file, format); 495 if (IS_EOF(file)) goto Bail; 496 } 497 498 for (i = 0; i < GLYPHPADOPTIONS; i++) { 499 bitmapSizes[i] = pcfGetINT32(file, format); 500 if (IS_EOF(file)) goto Bail; 501 } 502 503 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; 504 /* guard against completely empty font */ 505 bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); 506 if (!bitmaps) { 507 pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); 508 goto Bail; 509 } 510 FontFileRead(file, bitmaps, sizebitmaps); 511 if (IS_EOF(file)) goto Bail; 512 position += sizebitmaps; 513 514 if (PCF_BIT_ORDER(format) != bit) 515 BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); 516 if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { 517 switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { 518 case 1: 519 break; 520 case 2: 521 TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); 522 break; 523 case 4: 524 FourByteSwap((unsigned char *)bitmaps, sizebitmaps); 525 break; 526 } 527 } 528 if (PCF_GLYPH_PAD(format) != glyph) { 529 char *padbitmaps; 530 int sizepadbitmaps; 531 int old, 532 new; 533 xCharInfo *metric; 534 535 sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; 536 padbitmaps = malloc(sizepadbitmaps); 537 if (!padbitmaps) { 538 pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 539 goto Bail; 540 } 541 new = 0; 542 for (i = 0; i < nbitmaps; i++) { 543 old = offsets[i]; 544 metric = &metrics[i].metrics; 545 offsets[i] = new; 546 new += RepadBitmap(bitmaps + old, padbitmaps + new, 547 PCF_GLYPH_PAD(format), glyph, 548 metric->rightSideBearing - metric->leftSideBearing, 549 metric->ascent + metric->descent); 550 } 551 free(bitmaps); 552 bitmaps = padbitmaps; 553 } 554 for (i = 0; i < nbitmaps; i++) 555 metrics[i].bits = bitmaps + offsets[i]; 556 557 free(offsets); 558 offsets = NULL; 559 560 /* ink metrics ? */ 561 562 ink_metrics = NULL; 563 if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { 564 format = pcfGetLSB32(file); 565 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 566 !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 567 goto Bail; 568 } 569 if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 570 nink_metrics = pcfGetINT32(file, format); 571 else 572 nink_metrics = pcfGetINT16(file, format); 573 if (IS_EOF(file)) goto Bail; 574 if (nink_metrics != nmetrics) 575 goto Bail; 576 /* nmetrics already checked */ 577 ink_metrics = mallocarray(nink_metrics, sizeof(xCharInfo)); 578 if (!ink_metrics) { 579 pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", 580 nink_metrics, (int) sizeof(xCharInfo)); 581 goto Bail; 582 } 583 for (i = 0; i < nink_metrics; i++) 584 if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 585 if (!pcfGetMetric(file, format, ink_metrics + i)) 586 goto Bail; 587 } else { 588 if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) 589 goto Bail; 590 } 591 } 592 593 /* encoding */ 594 595 if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 596 goto Bail; 597 format = pcfGetLSB32(file); 598 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 599 goto Bail; 600 601 pFont->info.firstCol = pcfGetINT16(file, format); 602 pFont->info.lastCol = pcfGetINT16(file, format); 603 pFont->info.firstRow = pcfGetINT16(file, format); 604 pFont->info.lastRow = pcfGetINT16(file, format); 605 pFont->info.defaultCh = pcfGetINT16(file, format); 606 if (IS_EOF(file)) goto Bail; 607 if (pFont->info.firstCol > pFont->info.lastCol || 608 pFont->info.firstRow > pFont->info.lastRow || 609 pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; 610 611 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 612 (pFont->info.lastRow - pFont->info.firstRow + 1); 613 614 encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); 615 if (!encoding) { 616 pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", 617 nencoding, (int) sizeof(CharInfoPtr)); 618 goto Bail; 619 } 620 621 pFont->info.allExist = TRUE; 622 for (i = 0; i < nencoding; i++) { 623 encodingOffset = pcfGetINT16(file, format); 624 if (IS_EOF(file)) goto Bail; 625 if (encodingOffset == 0xFFFF) { 626 pFont->info.allExist = FALSE; 627 } else { 628 if(!encoding[SEGMENT_MAJOR(i)]) { 629 encoding[SEGMENT_MAJOR(i)]= 630 calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 631 if(!encoding[SEGMENT_MAJOR(i)]) 632 goto Bail; 633 } 634 ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; 635 } 636 } 637 638 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 639 640 if (hasBDFAccelerators) 641 if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) 642 goto Bail; 643 644 bitmapFont = malloc(sizeof *bitmapFont); 645 if (!bitmapFont) { 646 pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", 647 (int) sizeof *bitmapFont); 648 goto Bail; 649 } 650 651 bitmapFont->version_num = PCF_FILE_VERSION; 652 bitmapFont->num_chars = nmetrics; 653 bitmapFont->num_tables = ntables; 654 bitmapFont->metrics = metrics; 655 bitmapFont->ink_metrics = ink_metrics; 656 bitmapFont->bitmaps = bitmaps; 657 bitmapFont->encoding = encoding; 658 bitmapFont->pDefault = (CharInfoPtr) 0; 659 if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 660 unsigned int r, 661 c, 662 cols; 663 664 r = pFont->info.defaultCh >> 8; 665 c = pFont->info.defaultCh & 0xFF; 666 if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 667 pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 668 cols = pFont->info.lastCol - pFont->info.firstCol + 1; 669 r = r - pFont->info.firstRow; 670 c = c - pFont->info.firstCol; 671 bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); 672 } 673 } 674 bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 675 pFont->fontPrivate = (pointer) bitmapFont; 676 pFont->get_glyphs = bitmapGetGlyphs; 677 pFont->get_metrics = bitmapGetMetrics; 678 pFont->unload_font = pcfUnloadFont; 679 pFont->unload_glyphs = NULL; 680 pFont->bit = bit; 681 pFont->byte = byte; 682 pFont->glyph = glyph; 683 pFont->scan = scan; 684 free(tables); 685 return Successful; 686Bail: 687 free(ink_metrics); 688 if(encoding) { 689 for(i=0; i<NUM_SEGMENTS(nencoding); i++) 690 free(encoding[i]); 691 } 692 free(encoding); 693 free(bitmaps); 694 free(metrics); 695 free(pFont->info.props); 696 pFont->info.nprops = 0; 697 pFont->info.props = 0; 698 free (pFont->info.isStringProp); 699 free(bitmapFont); 700 free(tables); 701 free(offsets); 702 return AllocError; 703} 704 705int 706pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 707{ 708 PCFTablePtr tables; 709 int ntables; 710 CARD32 format; 711 CARD32 size; 712 int nencoding; 713 Bool hasBDFAccelerators; 714 715 pFontInfo->isStringProp = NULL; 716 pFontInfo->props = NULL; 717 pFontInfo->nprops = 0; 718 719 if (!(tables = pcfReadTOC(file, &ntables))) 720 goto Bail; 721 722 /* properties */ 723 724 if (!pcfGetProperties(pFontInfo, file, tables, ntables)) 725 goto Bail; 726 727 /* Use the old accelerators if no BDF accelerators are in the file */ 728 729 hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 730 if (!hasBDFAccelerators) 731 if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) 732 goto Bail; 733 734 /* encoding */ 735 736 if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 737 goto Bail; 738 format = pcfGetLSB32(file); 739 if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 740 goto Bail; 741 742 pFontInfo->firstCol = pcfGetINT16(file, format); 743 pFontInfo->lastCol = pcfGetINT16(file, format); 744 pFontInfo->firstRow = pcfGetINT16(file, format); 745 pFontInfo->lastRow = pcfGetINT16(file, format); 746 pFontInfo->defaultCh = pcfGetINT16(file, format); 747 if (IS_EOF(file)) goto Bail; 748 if (pFontInfo->firstCol > pFontInfo->lastCol || 749 pFontInfo->firstRow > pFontInfo->lastRow || 750 pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; 751 752 nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * 753 (pFontInfo->lastRow - pFontInfo->firstRow + 1); 754 755 pFontInfo->allExist = TRUE; 756 while (nencoding--) { 757 if (pcfGetINT16(file, format) == 0xFFFF) 758 pFontInfo->allExist = FALSE; 759 if (IS_EOF(file)) goto Bail; 760 } 761 if (IS_EOF(file)) goto Bail; 762 763 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 764 765 if (hasBDFAccelerators) 766 if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) 767 goto Bail; 768 769 free(tables); 770 return Successful; 771Bail: 772 pFontInfo->nprops = 0; 773 free (pFontInfo->props); 774 free (pFontInfo->isStringProp); 775 free(tables); 776 return AllocError; 777} 778 779static void 780pcfUnloadFont(FontPtr pFont) 781{ 782 BitmapFontPtr bitmapFont; 783 int i,nencoding; 784 785 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 786 free(bitmapFont->ink_metrics); 787 if(bitmapFont->encoding) { 788 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 789 (pFont->info.lastRow - pFont->info.firstRow + 1); 790 for(i=0; i<NUM_SEGMENTS(nencoding); i++) 791 free(bitmapFont->encoding[i]); 792 } 793 free(bitmapFont->encoding); 794 free(bitmapFont->bitmaps); 795 free(bitmapFont->metrics); 796 free(pFont->info.isStringProp); 797 free(pFont->info.props); 798 free(bitmapFont); 799 DestroyFontRec(pFont); 800} 801