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