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