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