bdfread.c revision 7f7f5e4e
1/* $Xorg: bdfread.c,v 1.5 2001/02/09 02:04:01 xorgcvs Exp $ */ 2 3/************************************************************************ 4Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 5 6 All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and its 9documentation for any purpose and without fee is hereby granted, 10provided that the above copyright notice appear in all copies and that 11both that copyright notice and this permission notice appear in 12supporting documentation, and that the name of Digital not be 13used in advertising or publicity pertaining to distribution of the 14software without specific, written prior permission. 15 16DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 17ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 18DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 19ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 20WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 22SOFTWARE. 23 24************************************************************************/ 25 26/* 27 28Copyright 1994, 1998 The Open Group 29 30Permission to use, copy, modify, distribute, and sell this software and its 31documentation for any purpose is hereby granted without fee, provided that 32the above copyright notice appear in all copies and that both that 33copyright notice and this permission notice appear in supporting 34documentation. 35 36The above copyright notice and this permission notice shall be included 37in all copies or substantial portions of the Software. 38 39THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 40OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 42IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 43OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 44ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 45OTHER DEALINGS IN THE SOFTWARE. 46 47Except as contained in this notice, the name of The Open Group shall 48not be used in advertising or otherwise to promote the sale, use or 49other dealings in this Software without prior written authorization 50from The Open Group. 51 52*/ 53/* $XFree86: xc/lib/font/bitmap/bdfread.c,v 1.12tsi Exp $ */ 54 55#ifdef HAVE_CONFIG_H 56#include <config.h> 57#endif 58 59#include <ctype.h> 60#include <X11/fonts/fntfilst.h> 61#include <X11/fonts/fontutil.h> 62/* use bitmap structure */ 63#include <X11/fonts/bitmap.h> 64#include <X11/fonts/bdfint.h> 65 66#if HAVE_STDINT_H 67#include <stdint.h> 68#elif !defined(INT32_MAX) 69#define INT32_MAX 0x7fffffff 70#endif 71 72#define INDICES 256 73#define MAXENCODING 0xFFFF 74#define BDFLINELEN 1024 75 76static Bool bdfPadToTerminal(FontPtr pFont); 77extern int bdfFileLineNum; 78 79/***====================================================================***/ 80 81static Bool 82bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte, 83 int glyph, int scan, CARD32 *sizes) 84{ 85 int widthBits, 86 widthBytes, 87 widthHexChars; 88 int height, 89 row; 90 int i, 91 inLineLen, 92 nextByte; 93 unsigned char *pInBits, 94 *picture, 95 *line = NULL; 96 unsigned char lineBuf[BDFLINELEN]; 97 98 widthBits = GLYPHWIDTHPIXELS(pCI); 99 height = GLYPHHEIGHTPIXELS(pCI); 100 101 widthBytes = BYTES_PER_ROW(widthBits, glyph); 102 if (widthBytes * height > 0) { 103 picture = malloc(widthBytes * height); 104 if (!picture) { 105 bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height); 106 goto BAILOUT; 107 } 108 } else 109 picture = NULL; 110 pCI->bits = (char *) picture; 111 112 if (sizes) { 113 for (i = 0; i < GLYPHPADOPTIONS; i++) 114 sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height; 115 } 116 nextByte = 0; 117 widthHexChars = BYTES_PER_ROW(widthBits, 1); 118 119/* 5/31/89 (ef) -- hack, hack, hack. what *am* I supposed to do with */ 120/* 0 width characters? */ 121 122 for (row = 0; row < height; row++) { 123 line = bdfGetLine(file, lineBuf, BDFLINELEN); 124 if (!line) 125 break; 126 127 if (widthBits == 0) { 128 if ((!line) || (bdfIsPrefix(line, "ENDCHAR"))) 129 break; 130 else 131 continue; 132 } 133 pInBits = line; 134 inLineLen = strlen((char *) pInBits); 135 136 if (inLineLen & 1) { 137 bdfError("odd number of characters in hex encoding\n"); 138 line[inLineLen++] = '0'; 139 line[inLineLen] = '\0'; 140 } 141 inLineLen >>= 1; 142 i = inLineLen; 143 if (i > widthHexChars) 144 i = widthHexChars; 145 for (; i > 0; i--, pInBits += 2) 146 picture[nextByte++] = bdfHexByte(pInBits); 147 148 /* pad if line is too short */ 149 if (inLineLen < widthHexChars) { 150 for (i = widthHexChars - inLineLen; i > 0; i--) 151 picture[nextByte++] = 0; 152 } else { 153 unsigned char mask; 154 155 mask = 0xff << (8 - (widthBits & 0x7)); 156 if (mask && picture[nextByte - 1] & ~mask) { 157 picture[nextByte - 1] &= mask; 158 } 159 } 160 161 if (widthBytes > widthHexChars) { 162 i = widthBytes - widthHexChars; 163 while (i-- > 0) 164 picture[nextByte++] = 0; 165 } 166 } 167 168 if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0)) 169 line = bdfGetLine(file, lineBuf, BDFLINELEN); 170 171 if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) { 172 bdfError("missing 'ENDCHAR'\n"); 173 goto BAILOUT; 174 } 175 if (nextByte != height * widthBytes) { 176 bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n", 177 nextByte, height, widthBytes); 178 goto BAILOUT; 179 } 180 if (picture != NULL) { 181 if (bit == LSBFirst) 182 BitOrderInvert(picture, nextByte); 183 if (bit != byte) { 184 if (scan == 2) 185 TwoByteSwap(picture, nextByte); 186 else if (scan == 4) 187 FourByteSwap(picture, nextByte); 188 } 189 } 190 return (TRUE); 191BAILOUT: 192 if (picture) 193 free(picture); 194 pCI->bits = NULL; 195 return (FALSE); 196} 197 198/***====================================================================***/ 199 200static Bool 201bdfSkipBitmap(FontFilePtr file, int height) 202{ 203 unsigned char *line; 204 int i = 0; 205 unsigned char lineBuf[BDFLINELEN]; 206 207 do { 208 line = bdfGetLine(file, lineBuf, BDFLINELEN); 209 i++; 210 } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height); 211 212 if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) { 213 bdfError("Error in bitmap, missing 'ENDCHAR'\n"); 214 return (FALSE); 215 } 216 return (TRUE); 217} 218 219/***====================================================================***/ 220 221static void 222bdfFreeFontBits(FontPtr pFont) 223{ 224 BitmapFontPtr bitmapFont; 225 BitmapExtraPtr bitmapExtra; 226 int i, nencoding; 227 228 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 229 bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; 230 free(bitmapFont->ink_metrics); 231 if(bitmapFont->encoding) { 232 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 233 (pFont->info.lastRow - pFont->info.firstRow + 1); 234 for(i=0; i<NUM_SEGMENTS(nencoding); i++) 235 free(bitmapFont->encoding[i]); 236 } 237 free(bitmapFont->encoding); 238 for (i = 0; i < bitmapFont->num_chars; i++) 239 free(bitmapFont->metrics[i].bits); 240 free(bitmapFont->metrics); 241 if (bitmapExtra) 242 { 243 free (bitmapExtra->glyphNames); 244 free (bitmapExtra->sWidths); 245 free (bitmapExtra); 246 } 247 free(pFont->info.props); 248 free(bitmapFont); 249} 250 251 252static Bool 253bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, 254 int bit, int byte, int glyph, int scan) 255{ 256 unsigned char *line; 257 register CharInfoPtr ci; 258 int i, 259 ndx, 260 nchars, 261 nignored; 262 unsigned int char_row, char_col; 263 int numEncodedGlyphs = 0; 264 CharInfoPtr *bdfEncoding[256]; 265 BitmapFontPtr bitmapFont; 266 BitmapExtraPtr bitmapExtra; 267 CARD32 *bitmapsSizes; 268 unsigned char lineBuf[BDFLINELEN]; 269 int nencoding; 270 271 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 272 bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; 273 274 if (bitmapExtra) { 275 bitmapsSizes = bitmapExtra->bitmapsSizes; 276 for (i = 0; i < GLYPHPADOPTIONS; i++) 277 bitmapsSizes[i] = 0; 278 } else 279 bitmapsSizes = NULL; 280 281 bzero(bdfEncoding, sizeof(bdfEncoding)); 282 bitmapFont->metrics = NULL; 283 ndx = 0; 284 285 line = bdfGetLine(file, lineBuf, BDFLINELEN); 286 287 if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) { 288 bdfError("bad 'CHARS' in bdf file\n"); 289 return (FALSE); 290 } 291 if (nchars < 1) { 292 bdfError("invalid number of CHARS in BDF file\n"); 293 return (FALSE); 294 } 295 if (nchars > INT32_MAX / sizeof(CharInfoRec)) { 296 bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, 297 sizeof(CharInfoRec)); 298 goto BAILOUT; 299 } 300 ci = calloc(nchars, sizeof(CharInfoRec)); 301 if (!ci) { 302 bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, 303 sizeof(CharInfoRec)); 304 goto BAILOUT; 305 } 306 bitmapFont->metrics = ci; 307 308 if (bitmapExtra) { 309 bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom)); 310 if (!bitmapExtra->glyphNames) { 311 bdfError("Couldn't allocate glyphNames (%d*%d)\n", 312 nchars, sizeof(Atom)); 313 goto BAILOUT; 314 } 315 } 316 if (bitmapExtra) { 317 bitmapExtra->sWidths = malloc(nchars * sizeof(int)); 318 if (!bitmapExtra->sWidths) { 319 bdfError("Couldn't allocate sWidth (%d *%d)\n", 320 nchars, sizeof(int)); 321 return FALSE; 322 } 323 } 324 line = bdfGetLine(file, lineBuf, BDFLINELEN); 325 pFont->info.firstRow = 256; 326 pFont->info.lastRow = 0; 327 pFont->info.firstCol = 256; 328 pFont->info.lastCol = 0; 329 nignored = 0; 330 for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) { 331 int t; 332 int wx; /* x component of width */ 333 int wy; /* y component of width */ 334 int bw; /* bounding-box width */ 335 int bh; /* bounding-box height */ 336 int bl; /* bounding-box left */ 337 int bb; /* bounding-box bottom */ 338 int enc, 339 enc2; /* encoding */ 340 unsigned char *p; /* temp pointer into line */ 341 char charName[100]; 342 int ignore; 343 344 if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) { 345 bdfError("bad character name in BDF file\n"); 346 goto BAILOUT; /* bottom of function, free and return error */ 347 } 348 if (bitmapExtra) 349 bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL); 350 351 line = bdfGetLine(file, lineBuf, BDFLINELEN); 352 if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) { 353 bdfError("bad 'ENCODING' in BDF file\n"); 354 goto BAILOUT; 355 } 356 if (enc < -1 || (t == 2 && enc2 < -1)) { 357 bdfError("bad ENCODING value"); 358 goto BAILOUT; 359 } 360 if (t == 2 && enc == -1) 361 enc = enc2; 362 ignore = 0; 363 if (enc == -1) { 364 if (!bitmapExtra) { 365 nignored++; 366 ignore = 1; 367 } 368 } else if (enc > MAXENCODING) { 369 bdfError("char '%s' has encoding too large (%d)\n", 370 charName, enc); 371 } else { 372 char_row = (enc >> 8) & 0xFF; 373 char_col = enc & 0xFF; 374 if (char_row < pFont->info.firstRow) 375 pFont->info.firstRow = char_row; 376 if (char_row > pFont->info.lastRow) 377 pFont->info.lastRow = char_row; 378 if (char_col < pFont->info.firstCol) 379 pFont->info.firstCol = char_col; 380 if (char_col > pFont->info.lastCol) 381 pFont->info.lastCol = char_col; 382 if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { 383 bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr)); 384 if (!bdfEncoding[char_row]) { 385 bdfError("Couldn't allocate row %d of encoding (%d*%d)\n", 386 char_row, INDICES, sizeof(CharInfoPtr)); 387 goto BAILOUT; 388 } 389 for (i = 0; i < 256; i++) 390 bdfEncoding[char_row][i] = (CharInfoPtr) NULL; 391 } 392 if (bdfEncoding[char_row] != NULL) { 393 bdfEncoding[char_row][char_col] = ci; 394 numEncodedGlyphs++; 395 } 396 } 397 398 line = bdfGetLine(file, lineBuf, BDFLINELEN); 399 if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { 400 bdfError("bad 'SWIDTH'\n"); 401 goto BAILOUT; 402 } 403 if (wy != 0) { 404 bdfError("SWIDTH y value must be zero\n"); 405 goto BAILOUT; 406 } 407 if (bitmapExtra) 408 bitmapExtra->sWidths[ndx] = wx; 409 410/* 5/31/89 (ef) -- we should be able to ditch the character and recover */ 411/* from all of these. */ 412 413 line = bdfGetLine(file, lineBuf, BDFLINELEN); 414 if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { 415 bdfError("bad 'DWIDTH'\n"); 416 goto BAILOUT; 417 } 418 if (wy != 0) { 419 bdfError("DWIDTH y value must be zero\n"); 420 goto BAILOUT; 421 } 422 line = bdfGetLine(file, lineBuf, BDFLINELEN); 423 if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) { 424 bdfError("bad 'BBX'\n"); 425 goto BAILOUT; 426 } 427 if ((bh < 0) || (bw < 0)) { 428 bdfError("character '%s' has a negative sized bitmap, %dx%d\n", 429 charName, bw, bh); 430 goto BAILOUT; 431 } 432 line = bdfGetLine(file, lineBuf, BDFLINELEN); 433 if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) { 434 for (p = line + strlen("ATTRIBUTES "); 435 (*p == ' ') || (*p == '\t'); 436 p++) 437 /* empty for loop */ ; 438 ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2); 439 line = bdfGetLine(file, lineBuf, BDFLINELEN); 440 } else 441 ci->metrics.attributes = 0; 442 443 if (!line || !bdfIsPrefix(line, "BITMAP")) { 444 bdfError("missing 'BITMAP'\n"); 445 goto BAILOUT; 446 } 447 /* collect data for generated properties */ 448 if ((strlen(charName) == 1)) { 449 if ((charName[0] >= '0') && (charName[0] <= '9')) { 450 pState->digitWidths += wx; 451 pState->digitCount++; 452 } else if (charName[0] == 'x') { 453 pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb; 454 } 455 } 456 if (!ignore) { 457 ci->metrics.leftSideBearing = bl; 458 ci->metrics.rightSideBearing = bl + bw; 459 ci->metrics.ascent = bh + bb; 460 ci->metrics.descent = -bb; 461 ci->metrics.characterWidth = wx; 462 ci->bits = NULL; 463 bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes); 464 ci++; 465 ndx++; 466 } else 467 bdfSkipBitmap(file, bh); 468 469 line = bdfGetLine(file, lineBuf, BDFLINELEN); /* get STARTCHAR or 470 * ENDFONT */ 471 } 472 473 if (ndx + nignored != nchars) { 474 bdfError("%d too few characters\n", nchars - (ndx + nignored)); 475 goto BAILOUT; 476 } 477 nchars = ndx; 478 bitmapFont->num_chars = nchars; 479 if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) { 480 bdfError("more characters than specified\n"); 481 goto BAILOUT; 482 } 483 if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) { 484 bdfError("missing 'ENDFONT'\n"); 485 goto BAILOUT; 486 } 487 if (numEncodedGlyphs == 0) 488 bdfWarning("No characters with valid encodings\n"); 489 490 nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) * 491 (pFont->info.lastCol - pFont->info.firstCol + 1); 492 bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*)); 493 if (!bitmapFont->encoding) { 494 bdfError("Couldn't allocate ppCI (%d,%d)\n", 495 NUM_SEGMENTS(nencoding), 496 sizeof(CharInfoPtr*)); 497 goto BAILOUT; 498 } 499 pFont->info.allExist = TRUE; 500 i = 0; 501 for (char_row = pFont->info.firstRow; 502 char_row <= pFont->info.lastRow; 503 char_row++) { 504 if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { 505 pFont->info.allExist = FALSE; 506 i += pFont->info.lastCol - pFont->info.firstCol + 1; 507 } else { 508 for (char_col = pFont->info.firstCol; 509 char_col <= pFont->info.lastCol; 510 char_col++) { 511 if (!bdfEncoding[char_row][char_col]) 512 pFont->info.allExist = FALSE; 513 else { 514 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 515 bitmapFont->encoding[SEGMENT_MAJOR(i)]= 516 calloc(BITMAP_FONT_SEGMENT_SIZE, 517 sizeof(CharInfoPtr)); 518 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) 519 goto BAILOUT; 520 } 521 ACCESSENCODINGL(bitmapFont->encoding,i) = 522 bdfEncoding[char_row][char_col]; 523 } 524 i++; 525 } 526 } 527 } 528 for (i = 0; i < 256; i++) 529 if (bdfEncoding[i]) 530 free(bdfEncoding[i]); 531 return (TRUE); 532BAILOUT: 533 for (i = 0; i < 256; i++) 534 if (bdfEncoding[i]) 535 free(bdfEncoding[i]); 536 /* bdfFreeFontBits will clean up the rest */ 537 return (FALSE); 538} 539 540/***====================================================================***/ 541 542static Bool 543bdfReadHeader(FontFilePtr file, bdfFileState *pState) 544{ 545 unsigned char *line; 546 char namebuf[BDFLINELEN]; 547 unsigned char lineBuf[BDFLINELEN]; 548 549 line = bdfGetLine(file, lineBuf, BDFLINELEN); 550 if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 || 551 !bdfStrEqual(namebuf, "2.1")) { 552 bdfError("bad 'STARTFONT'\n"); 553 return (FALSE); 554 } 555 line = bdfGetLine(file, lineBuf, BDFLINELEN); 556 if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) { 557 bdfError("bad 'FONT'\n"); 558 return (FALSE); 559 } 560 line = bdfGetLine(file, lineBuf, BDFLINELEN); 561 if (!line || !bdfIsPrefix(line, "SIZE")) { 562 bdfError("missing 'SIZE'\n"); 563 return (FALSE); 564 } 565 if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize, 566 &pState->resolution_x, &pState->resolution_y) != 3) { 567 bdfError("bad 'SIZE'\n"); 568 return (FALSE); 569 } 570 if (pState->pointSize < 1 || 571 pState->resolution_x < 1 || pState->resolution_y < 1) { 572 bdfError("SIZE values must be > 0\n"); 573 return (FALSE); 574 } 575 line = bdfGetLine(file, lineBuf, BDFLINELEN); 576 if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) { 577 bdfError("missing 'FONTBOUNDINGBOX'\n"); 578 return (FALSE); 579 } 580 return (TRUE); 581} 582 583/***====================================================================***/ 584 585static Bool 586bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) 587{ 588 int nProps, props_left, 589 nextProp; 590 char *stringProps; 591 FontPropPtr props; 592 char namebuf[BDFLINELEN], 593 secondbuf[BDFLINELEN], 594 thirdbuf[BDFLINELEN]; 595 unsigned char *line; 596 unsigned char lineBuf[BDFLINELEN]; 597 BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 598 599 line = bdfGetLine(file, lineBuf, BDFLINELEN); 600 if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) { 601 bdfError("missing 'STARTPROPERTIES'\n"); 602 return (FALSE); 603 } 604 if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) { 605 bdfError("bad 'STARTPROPERTIES'\n"); 606 return (FALSE); 607 } 608 pFont->info.isStringProp = NULL; 609 pFont->info.props = NULL; 610 pFont->info.nprops = 0; 611 612 stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char)); 613 pFont->info.isStringProp = stringProps; 614 if (stringProps == NULL) { 615 bdfError("Couldn't allocate stringProps (%d*%d)\n", 616 (nProps + BDF_GENPROPS), sizeof(Bool)); 617 goto BAILOUT; 618 } 619 pFont->info.props = props = calloc(nProps + BDF_GENPROPS, 620 sizeof(FontPropRec)); 621 if (props == NULL) { 622 bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS, 623 sizeof(FontPropRec)); 624 goto BAILOUT; 625 } 626 627 nextProp = 0; 628 props_left = nProps; 629 while (props_left-- > 0) { 630 line = bdfGetLine(file, lineBuf, BDFLINELEN); 631 if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) { 632 bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n", 633 nProps, nProps - props_left - 1); 634 goto BAILOUT; 635 } 636 while (*line && isspace(*line)) 637 line++; 638 639 switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) { 640 default: 641 bdfError("missing '%s' parameter value\n", namebuf); 642 goto BAILOUT; 643 644 case 2: 645 /* 646 * Possibilites include: valid quoted string with no white space 647 * valid integer value invalid value 648 */ 649 if (secondbuf[0] == '"') { 650 stringProps[nextProp] = TRUE; 651 props[nextProp].value = 652 bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); 653 if (!props[nextProp].value) 654 goto BAILOUT; 655 break; 656 } else if (bdfIsInteger(secondbuf)) { 657 stringProps[nextProp] = FALSE; 658 props[nextProp].value = atoi(secondbuf); 659 break; 660 } else { 661 bdfError("invalid '%s' parameter value\n", namebuf); 662 goto BAILOUT; 663 } 664 665 case 3: 666 /* 667 * Possibilites include: valid quoted string with some white space 668 * invalid value (reject even if second string is integer) 669 */ 670 if (secondbuf[0] == '"') { 671 stringProps[nextProp] = TRUE; 672 props[nextProp].value = 673 bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); 674 if (!props[nextProp].value) 675 goto BAILOUT; 676 break; 677 } else { 678 bdfError("invalid '%s' parameter value\n", namebuf); 679 goto BAILOUT; 680 } 681 } 682 props[nextProp].name = bdfForceMakeAtom(namebuf, NULL); 683 if (props[nextProp].name == None) { 684 bdfError("Empty property name.\n"); 685 goto BAILOUT; 686 } 687 if (!bdfSpecialProperty(pFont, &props[nextProp], 688 stringProps[nextProp], pState)) 689 nextProp++; 690 } 691 692 line = bdfGetLine(file, lineBuf, BDFLINELEN); 693 if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) { 694 bdfError("missing 'ENDPROPERTIES'\n"); 695 goto BAILOUT; 696 } 697 if (!pState->haveFontAscent || !pState->haveFontDescent) { 698 bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n"); 699 goto BAILOUT; 700 } 701 if (bitmapFont->bitmapExtra) { 702 bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent; 703 bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent; 704 } 705 if (!pState->pointSizeProp) { 706 props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL); 707 props[nextProp].value = (INT32) (pState->pointSize * 10.0); 708 stringProps[nextProp] = FALSE; 709 pState->pointSizeProp = &props[nextProp]; 710 nextProp++; 711 } 712 if (!pState->fontProp) { 713 props[nextProp].name = bdfForceMakeAtom("FONT", NULL); 714 props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL); 715 stringProps[nextProp] = TRUE; 716 pState->fontProp = &props[nextProp]; 717 nextProp++; 718 } 719 if (!pState->weightProp) { 720 props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL); 721 props[nextProp].value = -1; /* computed later */ 722 stringProps[nextProp] = FALSE; 723 pState->weightProp = &props[nextProp]; 724 nextProp++; 725 } 726 if (!pState->resolutionProp && 727 pState->resolution_x == pState->resolution_y) { 728 props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL); 729 props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27); 730 stringProps[nextProp] = FALSE; 731 pState->resolutionProp = &props[nextProp]; 732 nextProp++; 733 } 734 if (!pState->resolutionXProp) { 735 props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL); 736 props[nextProp].value = (INT32) pState->resolution_x; 737 stringProps[nextProp] = FALSE; 738 pState->resolutionProp = &props[nextProp]; 739 nextProp++; 740 } 741 if (!pState->resolutionYProp) { 742 props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL); 743 props[nextProp].value = (INT32) pState->resolution_y; 744 stringProps[nextProp] = FALSE; 745 pState->resolutionProp = &props[nextProp]; 746 nextProp++; 747 } 748 if (!pState->xHeightProp) { 749 props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL); 750 props[nextProp].value = -1; /* computed later */ 751 stringProps[nextProp] = FALSE; 752 pState->xHeightProp = &props[nextProp]; 753 nextProp++; 754 } 755 if (!pState->quadWidthProp) { 756 props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL); 757 props[nextProp].value = -1; /* computed later */ 758 stringProps[nextProp] = FALSE; 759 pState->quadWidthProp = &props[nextProp]; 760 nextProp++; 761 } 762 pFont->info.nprops = nextProp; 763 return (TRUE); 764BAILOUT: 765 if (pFont->info.isStringProp) { 766 free(pFont->info.isStringProp); 767 pFont->info.isStringProp = NULL; 768 } 769 if (pFont->info.props) { 770 free(pFont->info.props); 771 pFont->info.props = NULL; 772 } 773 while (line && bdfIsPrefix(line, "ENDPROPERTIES")) 774 line = bdfGetLine(file, lineBuf, BDFLINELEN); 775 return (FALSE); 776} 777 778/***====================================================================***/ 779 780static void 781bdfUnloadFont(FontPtr pFont) 782{ 783 bdfFreeFontBits (pFont); 784 DestroyFontRec(pFont); 785} 786 787int 788bdfReadFont(FontPtr pFont, FontFilePtr file, 789 int bit, int byte, int glyph, int scan) 790{ 791 bdfFileState state; 792 xCharInfo *min, 793 *max; 794 BitmapFontPtr bitmapFont; 795 796 pFont->fontPrivate = 0; 797 798 bzero(&state, sizeof(bdfFileState)); 799 bdfFileLineNum = 0; 800 801 if (!bdfReadHeader(file, &state)) 802 goto BAILOUT; 803 804 bitmapFont = calloc(1, sizeof(BitmapFontRec)); 805 if (!bitmapFont) { 806 bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec)); 807 goto BAILOUT; 808 } 809 810 pFont->fontPrivate = (pointer) bitmapFont; 811 bitmapFont->metrics = 0; 812 bitmapFont->ink_metrics = 0; 813 bitmapFont->bitmaps = 0; 814 bitmapFont->encoding = 0; 815 bitmapFont->pDefault = NULL; 816 817 bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec)); 818 if (!bitmapFont->bitmapExtra) { 819 bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec)); 820 goto BAILOUT; 821 } 822 823 bitmapFont->bitmapExtra->glyphNames = 0; 824 bitmapFont->bitmapExtra->sWidths = 0; 825 826 if (!bdfReadProperties(file, pFont, &state)) 827 goto BAILOUT; 828 829 if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan)) 830 goto BAILOUT; 831 832 if (state.haveDefaultCh) { 833 unsigned int r, c, cols; 834 835 r = pFont->info.defaultCh >> 8; 836 c = pFont->info.defaultCh & 0xFF; 837 if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 838 pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 839 cols = pFont->info.lastCol - pFont->info.firstCol + 1; 840 r = r - pFont->info.firstRow; 841 c = c - pFont->info.firstCol; 842 bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding, 843 r * cols + c); 844 } 845 } 846 pFont->bit = bit; 847 pFont->byte = byte; 848 pFont->glyph = glyph; 849 pFont->scan = scan; 850 pFont->info.anamorphic = FALSE; 851 pFont->info.cachable = TRUE; 852 bitmapComputeFontBounds(pFont); 853 if (FontCouldBeTerminal(&pFont->info)) { 854 bdfPadToTerminal(pFont); 855 bitmapComputeFontBounds(pFont); 856 } 857 FontComputeInfoAccelerators(&pFont->info); 858 if (bitmapFont->bitmapExtra) 859 FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info); 860 if (pFont->info.constantMetrics) { 861 if (!bitmapAddInkMetrics(pFont)) { 862 bdfError("Failed to add bitmap ink metrics\n"); 863 goto BAILOUT; 864 } 865 } 866 if (bitmapFont->bitmapExtra) 867 bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics; 868 869 bitmapComputeFontInkBounds(pFont); 870/* ComputeFontAccelerators (pFont); */ 871 872 /* generate properties */ 873 min = &pFont->info.ink_minbounds; 874 max = &pFont->info.ink_maxbounds; 875 if (state.xHeightProp && (state.xHeightProp->value == -1)) 876 state.xHeightProp->value = state.exHeight ? 877 state.exHeight : min->ascent; 878 879 if (state.quadWidthProp && (state.quadWidthProp->value == -1)) 880 state.quadWidthProp->value = state.digitCount ? 881 (INT32) (state.digitWidths / state.digitCount) : 882 (min->characterWidth + max->characterWidth) / 2; 883 884 if (state.weightProp && (state.weightProp->value == -1)) 885 state.weightProp->value = bitmapComputeWeight(pFont); 886 887 pFont->get_glyphs = bitmapGetGlyphs; 888 pFont->get_metrics = bitmapGetMetrics; 889 pFont->unload_font = bdfUnloadFont; 890 pFont->unload_glyphs = NULL; 891 return Successful; 892BAILOUT: 893 if (pFont->fontPrivate) 894 bdfFreeFontBits (pFont); 895 return AllocError; 896} 897 898int 899bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 900{ 901 FontRec font; 902 int ret; 903 904 bzero(&font, sizeof (FontRec)); 905 906 ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1); 907 if (ret == Successful) { 908 *pFontInfo = font.info; 909 font.info.props = 0; 910 font.info.isStringProp = 0; 911 font.info.nprops = 0; 912 bdfFreeFontBits (&font); 913 } 914 return ret; 915} 916 917static Bool 918bdfPadToTerminal(FontPtr pFont) 919{ 920 BitmapFontPtr bitmapFont; 921 BitmapExtraPtr bitmapExtra; 922 int i; 923 int new_size; 924 CharInfoRec new; 925 int w, 926 h; 927 928 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 929 930 bzero(&new, sizeof(CharInfoRec)); 931 new.metrics.ascent = pFont->info.fontAscent; 932 new.metrics.descent = pFont->info.fontDescent; 933 new.metrics.leftSideBearing = 0; 934 new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth; 935 new.metrics.characterWidth = new.metrics.rightSideBearing; 936 new_size = BYTES_FOR_GLYPH(&new, pFont->glyph); 937 938 for (i = 0; i < bitmapFont->num_chars; i++) { 939 new.bits = malloc(new_size); 940 if (!new.bits) { 941 bdfError("Couldn't allocate bits (%d)\n", new_size); 942 return FALSE; 943 } 944 FontCharReshape(pFont, &bitmapFont->metrics[i], &new); 945 new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes; 946 free(bitmapFont->metrics[i].bits); 947 bitmapFont->metrics[i] = new; 948 } 949 bitmapExtra = bitmapFont->bitmapExtra; 950 if (bitmapExtra) { 951 w = GLYPHWIDTHPIXELS(&new); 952 h = GLYPHHEIGHTPIXELS(&new); 953 for (i = 0; i < GLYPHPADOPTIONS; i++) 954 bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars * 955 (BYTES_PER_ROW(w, 1 << i) * h); 956 } 957 return TRUE; 958} 959