|
|
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.