|
|
1.1 ! root 1: ! 2: /* ! 3: * ! 4: * A few routines that read and process raster files supplied by Imagen. ! 5: * ! 6: * Impress, at least at the time these routines were written, only allowed ! 7: * us to use families 0 to 95. That imposes a limit on the total number of ! 8: * raster files that any one job can use, unless we do some kind of memory ! 9: * management, and that in turn restricts the number of entries in array ! 10: * fam_data[] to 96. Unless this limit is changed MAXFAMILY should never be ! 11: * defined to be greater than 95. ! 12: * ! 13: */ ! 14: ! 15: ! 16: #include <stdio.h> ! 17: #include <sys/types.h> ! 18: #include <sys/stat.h> ! 19: ! 20: #include "ext.h" /* external variable definitions */ ! 21: #include "gen.h" /* definitions used by everyone */ ! 22: #include "rast.h" /* raster file definitions */ ! 23: #include "impcodes.h" /* Impress 2.0 opcodes */ ! 24: ! 25: ! 26: Rst rst[] = RST_INIT; /* describes raster file structure */ ! 27: ! 28: Rastdata fam_data[MAXFAMILY+1]; /* data about raster files we've read */ ! 29: ! 30: int fam_num = 0; /* use this as next family number */ ! 31: int next_fam = 0; /* next free spot in fam_data[] */ ! 32: int cur_fam = 0; /* family number we're using right now */ ! 33: int last_fam = MAXFAMILY+1; /* last one we told printer about */ ! 34: Rastdata *fam = NULL; /* &fam_data[cur_fam] */ ! 35: ! 36: int rast_res = RAST_RES; /* raster table resolution */ ! 37: ! 38: ! 39: /*****************************************************************************/ ! 40: ! 41: ! 42: getfamdata(f, s) ! 43: ! 44: ! 45: char *f; /* find data for this font */ ! 46: int s; /* in this point size */ ! 47: ! 48: ! 49: { ! 50: ! 51: ! 52: int i; /* check fam_data[i] next */ ! 53: ! 54: ! 55: /* ! 56: * ! 57: * Looks for the family data for font *f and size s in the fam_data[] ! 58: * data structure. Returns the index where it was found, or next_fam ! 59: * if not found. ! 60: * ! 61: */ ! 62: ! 63: ! 64: for ( i = 0; i < next_fam; i++ ) ! 65: if ( fam_data[i].size == s && strcmp(f, fam_data[i].name) == 0 ) ! 66: break; ! 67: ! 68: return(i); ! 69: ! 70: } /* End of getfamdata */ ! 71: ! 72: ! 73: /*****************************************************************************/ ! 74: ! 75: ! 76: getrastdata(f, s) ! 77: ! 78: ! 79: char *f; /* use this font's raster file */ ! 80: int s; /* in this point size */ ! 81: ! 82: ! 83: { ! 84: ! 85: ! 86: int i; /* loop index for setting families */ ! 87: ! 88: ! 89: /* ! 90: * ! 91: * Called to find the raster file info for font f, size s in fam_data[]. ! 92: * If it's not there it will be read in from the appropriate file in ! 93: * *rastdir and all the required info will be added to location ! 94: * next_fam in fam_data[]. ! 95: * ! 96: * I'm assuming that each raster file contains at most 128 glyphs. If ! 97: * that's not the case we'll need to change the way things are done ! 98: * because Impress only allows 128 members in each family. Brian took ! 99: * account of of larger raster files in di10.c and it wouldn't be all ! 100: * that difficult to do it here too, but I don't think it's necessary. ! 101: * ! 102: */ ! 103: ! 104: ! 105: cur_fam = getfamdata(f, s); /* use this family next */ ! 106: fam = &fam_data[cur_fam]; /* its entry in fam_data[] */ ! 107: ! 108: if ( cur_fam >= next_fam ) { /* didn't find it */ ! 109: if ( next_fam > MAXFAMILY ) /* only use families 0 to 95 */ ! 110: error(FATAL, "job uses too many raster files"); ! 111: ! 112: strncpy(fam->name, f, L_FNAME); /* initialze some of the fields */ ! 113: fam->name[L_FNAME-1] = '\0'; ! 114: fam->size = s; ! 115: fam->rst = NULL; ! 116: fam->advance = (int *) rastalloc((MAXMEMBER+1) * sizeof(int), FALSE); ! 117: ! 118: for ( i = 0; i < ROT_COUNT; i++ ) { ! 119: fam->chused[i] = (unsigned char *) rastalloc((MAXMEMBER+BYTE)/BYTE, TRUE, 0); ! 120: fam->fam[i] = -1; ! 121: } /* End for */ ! 122: ! 123: next_fam++; /* can only use it once */ ! 124: } /* End if */ ! 125: ! 126: if ( fam->rst == NULL ) /* need to read the whole raster file */ ! 127: readrastfile(f, s); ! 128: ! 129: } /* End of getrastdata */ ! 130: ! 131: ! 132: /*****************************************************************************/ ! 133: ! 134: ! 135: readrastfile(f, s) ! 136: ! 137: ! 138: char *f; /* name of the raster file */ ! 139: int s; /* in this point size */ ! 140: ! 141: ! 142: { ! 143: ! 144: ! 145: char name[100]; /* raster file pathname built up here */ ! 146: int fd; /* file descriptor for *name */ ! 147: struct stat buf; /* used to get raster file size */ ! 148: ! 149: ! 150: /* ! 151: * ! 152: * Reads the raster file for font f in size s from directory *rastdir ! 153: * and initializes some of the required fields in fam_data[cur_fam]. ! 154: * ! 155: * First we try to open the appropriate raster file. Then we determine ! 156: * its size in bytes and try to allocate enough memory for the whole file. ! 157: * After we've successfully read it we close the file and then initialize ! 158: * the rest of the fields in fam_data[cur_fam]. ! 159: * ! 160: * I've made allowances for two types of raster file naming conventions. ! 161: * The most common is the one that troff's post-processor will be using. ! 162: * The raster file names all begin with the string "font." and end with ! 163: * the suffix size. For example the raster table for the Roman font in size ! 164: * 10 would be called R.10. The other convention is the one you'll find ! 165: * in all the raster files supplied directly from Imagen (as of 9/15 anyway). ! 166: * In this case the file names all begin with the prefix string "*font.r" ! 167: * and again end with the size. For example the raster file for font cmti ! 168: * in size 12 would be cmti.r12. Since this routine is used by programs that ! 169: * expect both conventions I've written it to try the two different raster ! 170: * file names before giving up. ! 171: * ! 172: */ ! 173: ! 174: ! 175: sprintf(name, "%s/%s.%d", rastdir, f, s); ! 176: if ( (fd = open(name, 0)) == -1 ) { ! 177: sprintf(name, "%s/%s.r%d", rastdir, f, s); ! 178: if ( (fd = open(name, 0)) == -1 ) ! 179: error(FATAL, "can't open raster file for font %s, size %d", f, s); ! 180: } /* End if */ ! 181: ! 182: if ( fstat(fd, &buf) == -1 ) ! 183: error(FATAL, "can't get file size for %s", name); ! 184: ! 185: fam->rst = rastalloc(buf.st_size, FALSE); ! 186: ! 187: if ( read(fd, fam->rst, buf.st_size) != buf.st_size ) ! 188: error(FATAL, "can't read raster file %s", name); ! 189: ! 190: close(fd); /* all done with it - for now anyway */ ! 191: ! 192: fam->glyphdir = getvalue(P_GLYDIR); ! 193: fam->first = getvalue(P_FIRSTGLY); ! 194: fam->last = getvalue(P_LASTGLY); ! 195: ! 196: if ( (fam->mag = getvalue(P_MAG)) <= 0 ) ! 197: fam->mag = 1000; ! 198: ! 199: } /* End of readrastfile */ ! 200: ! 201: ! 202: /*****************************************************************************/ ! 203: ! 204: ! 205: freerast(count) ! 206: ! 207: ! 208: int count; /* max number of calls to free() */ ! 209: ! 210: ! 211: { ! 212: ! 213: ! 214: int called; /* number of calls made so far */ ! 215: int i; /* loop index */ ! 216: ! 217: ! 218: /* ! 219: * ! 220: * Tries to free all the memory used to store raster file data for ! 221: * at most count entires in array fam_data[]. The actual number of ! 222: * calls to free() is returned to the caller. A return value of 0 ! 223: * obviously means there's no more memory to release. We don't want to ! 224: * free the memory used to keep track of the characters we've downloaded ! 225: * because we may want to use this raster file later on and we'll need to ! 226: * know which glyphs have been downloaded. ! 227: * ! 228: * Although I don't expect to use this routine often, some of the ! 229: * raster files are huge and there will undoubtedly be a few jobs ! 230: * that won't be able to keep all the required raster data in memory ! 231: * at the same time. ! 232: * ! 233: */ ! 234: ! 235: ! 236: for ( called = 0, i = 0; i < next_fam && called < count; i++ ) ! 237: if ( fam_data[i].rst != NULL ) { ! 238: free(fam_data[i].rst); ! 239: fam_data[i].rst = NULL; ! 240: called++; ! 241: } /* End if */ ! 242: ! 243: return(called); ! 244: ! 245: } /* End of freerast */ ! 246: ! 247: ! 248: /*****************************************************************************/ ! 249: ! 250: ! 251: resetrast() ! 252: ! 253: ! 254: { ! 255: ! 256: ! 257: int i, j; /* loop indices - family and angle */ ! 258: ! 259: ! 260: /* ! 261: * ! 262: * Called when we want to clear the fam_data[] array, free all the memory ! 263: * associated with each raster file, and reset all the variables used to ! 264: * access the raster file info. Not used when we're generating Impress ! 265: * commands used to print files, but it may be useful when we build and ! 266: * edit raster files and troff's ASCII font files - maybe it shouldn't ! 267: * be in this file. ! 268: * ! 269: */ ! 270: ! 271: ! 272: for ( i = 0; i < next_fam; i++ ) { ! 273: free(fam_data[i].rst); ! 274: free(fam_data[i].advance); ! 275: fam_data[i].name[0] = '\0'; ! 276: fam_data[i].size = 0; ! 277: for ( j = 0; j < ROT_COUNT; j++ ) ! 278: free(fam_data[i].chused[j]); ! 279: } /* End for */ ! 280: ! 281: next_fam = 0; ! 282: cur_fam = 0; ! 283: last_fam = -1; ! 284: fam = NULL; ! 285: ! 286: } /* End of resetrast */ ! 287: ! 288: ! 289: /*****************************************************************************/ ! 290: ! 291: ! 292: char *rastalloc(size, init, val) ! 293: ! 294: ! 295: unsigned size; /* allocate this many bytes */ ! 296: int init; /* if TRUE initialize bytes */ ! 297: int val; /* to these values */ ! 298: ! 299: ! 300: { ! 301: ! 302: ! 303: char *ptr; /* block of memory we just got */ ! 304: int i; /* loop index for initialization */ ! 305: ! 306: ! 307: /* ! 308: * ! 309: * Tries to allocate a block of memory that's large enough to be used for ! 310: * storage of size bytes. If init is TRUE the memory will be initialized ! 311: * to val. It's assumed that the memory is going to be used to store ! 312: * a raster file or other related data. We'll keep trying to get enough ! 313: * memory as long as some is being used for other raster files. ! 314: * ! 315: */ ! 316: ! 317: ! 318: while ( (ptr = (char *) malloc(size)) == NULL ) ! 319: if ( freerast(1) == 0 ) ! 320: error(FATAL, "can't allocate memory for raster file"); ! 321: ! 322: if ( init == TRUE ) /* set all bytes to val */ ! 323: for ( i = 0; i < size; i++ ) ! 324: *(ptr + i) = val; ! 325: ! 326: return(ptr); ! 327: ! 328: } /* End of rastalloc */ ! 329: ! 330: ! 331: /*****************************************************************************/ ! 332: ! 333: ! 334: download(c, advance, angle, fp) ! 335: ! 336: ! 337: int c; /* download this glyph? */ ! 338: int advance; /* using this as the advance width */ ! 339: int angle; /* glyph rotation - just 2 bits */ ! 340: FILE *fp; /* Impress commands written here */ ! 341: ! 342: ! 343: { ! 344: ! 345: ! 346: Glyph glyph; /* all of c's important data */ ! 347: int map_size; /* bytes needed to store the bitmap */ ! 348: int i; /* loop index for downloading glyph */ ! 349: ! 350: ! 351: /* ! 352: * ! 353: * Downloads glyph number c, using the raster file fam->rst and advance ! 354: * as the character advance. All the Impress commands are written to FILE ! 355: * *fp. If advance is greater than or equal to zero we'll assume the caller ! 356: * wants to use the value as the character advance for the glyph, otherwise ! 357: * we'll get the value from the raster file. Returns the member number in ! 358: * the current family that corresponds to glyph c. ! 359: * ! 360: * I've added glyph rotation capabilities to this routine. The parameter ! 361: * angle selects the absolute orientation of the glyph. Each angle needs ! 362: * to be handled as a separate family. That means we'll want separate ! 363: * chused bitmaps and family numbers for each orientation. I've added ! 364: * the necessary fields to Rastdata. The fam[] field is new and really ! 365: * needed so we don't waste our limited family numbers on orientations ! 366: * that will never be used in the document. The Impress family is no ! 367: * longer the font's index in fam_data[]. ! 368: * ! 369: * Does much of the stuff handled by xychar() in di10.c except for the ! 370: * positioning of the reference point and printing the member. I've tried ! 371: * to make things a little more general so I'm assuming that whoever calls ! 372: * it has done the appropriate positioning and will take care of printing ! 373: * the glyph. ! 374: * ! 375: */ ! 376: ! 377: ! 378: if ( c < fam->first || c > fam->last ) ! 379: error(FATAL, "glyph %d out of range for font %s", c, fam->name); ! 380: ! 381: if ( fam->fam[angle] != last_fam ) { /* using a new family now */ ! 382: if ( fam->fam[angle] == -1 ) { ! 383: fam->fam[angle] = fam_num; ! 384: if ( (fam_num += 1 + fam->last/128) > MAXFAMILY ) ! 385: error(FATAL, "job uses too many families"); ! 386: } /* End if */ ! 387: putc(ASF, fp); ! 388: putc(last_fam = fam->fam[angle] + c/128, fp); ! 389: } /* End if */ ! 390: ! 391: if ( ! checkbit(fam->chused[angle], c) ) { /* first use of this glyph */ ! 392: setbit(fam->chused[angle], c); /* don't download it again */ ! 393: ! 394: fam->advance[c] = (advance < 0 ) ? PIXEL_WIDTH(getvalue(G_CHWIDTH, c), rast_res) : advance; ! 395: ! 396: glyph.xref = getvalue(G_XREF, c); /* we'll need these soon */ ! 397: glyph.yref = getvalue(G_YREF, c); ! 398: glyph.width = getvalue(G_WIDTH, c); ! 399: glyph.height = getvalue(G_HEIGHT, c); ! 400: glyph.advance = fam->advance[c]; ! 401: glyph.bptr = fam->rst + getvalue(G_BPTR, c); ! 402: ! 403: if ( angle != ROT_0 ) ! 404: rotate(&glyph, angle); ! 405: ! 406: if ( (map_size = glyph.height * ((glyph.width + BYTE - 1) / BYTE)) > 0 ) { ! 407: putc(ABGLY, fp); /* define the glyph */ ! 408: putint((angle << 14) | (last_fam << 7) | c % 128, fp); ! 409: putint(glyph.advance, fp); ! 410: putint(glyph.width, fp); ! 411: putint(glyph.xref, fp); ! 412: putint(glyph.height, fp); ! 413: putint(glyph.yref, fp); ! 414: ! 415: for ( i = map_size; i--; ) /* followed by its bitmap */ ! 416: putc(*glyph.bptr++, fp); ! 417: } else error(NON_FATAL, "Bad glyph - font %s, glyph %d", fam->name, c); ! 418: } /* End if */ ! 419: ! 420: return(c % 128); ! 421: ! 422: } /* End of download */ ! 423: ! 424: ! 425: /*****************************************************************************/ ! 426: ! 427: ! 428: unsigned getvalue(field, ch) ! 429: ! 430: ! 431: int field; /* position in rst[] */ ! 432: int ch; /* character number - for glyphs */ ! 433: ! 434: ! 435: { ! 436: ! 437: ! 438: register int n; /* number of bytes in the field */ ! 439: register char *p; /* start of the field */ ! 440: register unsigned value; /* result after decoding field */ ! 441: ! 442: ! 443: /* ! 444: * ! 445: * Called to figure out the value field in the current family's raster file. ! 446: * Right now things don't work for strings, but they're not really important. ! 447: * ! 448: * You'll see quite a few calls to this routine without the parameter ch. ! 449: * It's only used when we're accessing the glyph directory so I've omitted ! 450: * passing a value when we're looking at the preamble. ! 451: * ! 452: */ ! 453: ! 454: ! 455: n = rst[field].size; /* number of bytes we want to grab */ ! 456: ! 457: p = fam->rst + rst[field].offset; /* right except for glyph directory */ ! 458: ! 459: if ( rst[field].glyphdir == TRUE ) /* it's really part of the directory */ ! 460: p += GLYPH_PTR(ch); ! 461: ! 462: value = (rst[field].type == INTEGER && (*p & 0200)) ? ~0 : 0; ! 463: ! 464: for ( ; n > 0; n--, p++ ) ! 465: value = (value << BYTE) | (*p & BMASK); ! 466: ! 467: return(value); ! 468: ! 469: } /* End of getvalue */ ! 470: ! 471: ! 472: /*****************************************************************************/ ! 473: ! 474: ! 475: checkbit(p, n) ! 476: ! 477: ! 478: char *p; /* start of the bitmap */ ! 479: int n; /* see if this bit is set */ ! 480: ! 481: ! 482: { ! 483: ! 484: ! 485: /* ! 486: * ! 487: * Returns the value (0 or 1) set in the n-th bit in the bitmap that ! 488: * starts at address p. Primarily used to keep track of which glyphs ! 489: * have already been downloaded, but it's also needed in the routine ! 490: * that dumps bitmaps out to files. It probably should be defined as ! 491: * a macro. ! 492: * ! 493: */ ! 494: ! 495: ! 496: return(((p[n / BYTE] >> ((BYTE - 1) - n % BYTE)) & 01)); ! 497: ! 498: } /* End of checkbit */ ! 499: ! 500: ! 501: /*****************************************************************************/ ! 502: ! 503: ! 504: setbit(p, n) ! 505: ! 506: ! 507: char *p; /* start of the bitmap - again */ ! 508: int n; /* bit that we want to set in p[] */ ! 509: ! 510: ! 511: { ! 512: ! 513: ! 514: /* ! 515: * ! 516: * Turns on the n-th bit in the bitmap that starts at address p. This ! 517: * routine is really only used to keep track of the glyphs that have ! 518: * already been downloaded. Again it could easily be defined as a macro. ! 519: * ! 520: */ ! 521: ! 522: ! 523: p[n / BYTE] |= 01 << ((BYTE - 1) - n % BYTE); ! 524: ! 525: } /* End of setbit */ ! 526: ! 527: ! 528: /*****************************************************************************/ ! 529: ! 530: ! 531: dump_glyph(n, fp) ! 532: ! 533: ! 534: int n; /* glyph number we want to display */ ! 535: FILE *fp; /* everything's written here */ ! 536: ! 537: ! 538: { ! 539: ! 540: ! 541: int height; /* pixel height of the bitmap */ ! 542: int width; /* width of the rows in pixels */ ! 543: int xref; /* x coordinate of reference point */ ! 544: int yref; /* same but for y coordinate */ ! 545: int chwidth; /* width of the character */ ! 546: int rwid; /* number of bytes per bitmap row */ ! 547: int i, j; /* loop indices for the bitmap */ ! 548: char *bptr; /* start of the glyph's bitmap */ ! 549: ! 550: ! 551: /* ! 552: * ! 553: * Really just a debugging routine that's used to dump the bitmap and ! 554: * other glyph data for character n out to FILE *fp. ! 555: * ! 556: */ ! 557: ! 558: ! 559: height = getvalue(G_HEIGHT, n); ! 560: width = getvalue(G_WIDTH, n); ! 561: xref = getvalue(G_XREF, n); ! 562: yref = getvalue(G_YREF, n); ! 563: chwidth = getvalue(G_CHWIDTH, n); ! 564: bptr = fam->rst + getvalue(G_BPTR, n); ! 565: ! 566: rwid = (width + BYTE - 1) / BYTE; ! 567: ! 568: fprintf(fp, "GLYPH NUMBER %d Character Width = %d\n", n, PIXEL_WIDTH(chwidth, rast_res)); ! 569: fprintf(fp, " Raster Data: height = %d, width = %d, xref = %d, yref = %d, chwidth = %d\n",height, width, xref, yref, chwidth); ! 570: ! 571: for ( j = 0; j < height; j++ ) { ! 572: for ( i = 0; i < width; i++ ) ! 573: if ( checkbit(bptr, j * rwid * BYTE + i) ) ! 574: putc('X', fp); ! 575: else putc('.', fp); ! 576: putc('\n', fp); ! 577: } /* End for */ ! 578: ! 579: } /* End of dump_glyph */ ! 580: ! 581: ! 582: /*****************************************************************************/ ! 583: ! 584:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.