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