1 /********************************************************************
2 *
3 * Harris - Emulator specific font stuff: bitmap files.
4 *
5 * @(#)font2.c 1.2 (CWI) 87/07/10
6 *
7 *******************************************************************/
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/file.h>
11 #include <errno.h>
12 #include "the.h"
13 #include "defs.h" /* harris font definitions */
14
15
16 #define BYTE 8
17
18
19 struct chardata {
20 short charno; /* character number */
21 int XO, YO; /* origin of char rel. to troff positions */
22 int width, height; /* scaled size in bits */
23 char *cbitmap; /* bitmap of character */
24 short nbytes; /* length of bitmap */
25 struct chardata *nextchar;
26 };
27
28 struct fontadmin {
29 short physical;
30 short size;
31 struct chardata *ch[128+1]; /* we start at index 1 */
32 struct fontadmin *f;
33 };
34
35
36
37 private struct fontadmin *currentfnt;
38 private struct fontadmin firstf;
39
40 extern short *pstab;
41 extern int size;
42 extern char buffer[];
43 extern int hpos, vpos, vorigin;
44 extern int virtRES;
45 extern int debug, dbg;
46 extern int slant;
47 extern double slantoffset;
48
49 extern int errno;
50
51
52 char *getfile();
53
54 struct fontadmin *findfont();
55 struct fontadmin *falloc();
56
57 extern char *malloc();
58
59
60
61
initfonts()62 initfonts()
63 {
64 currentfnt = (struct fontadmin *) 0; /* zero it out to start! */
65 firstf.physical = 0;
66 firstf.size = 0;
67 }
68
69
70
71 /*
72 * putcode: get the necessary character data and write it.
73 *
74 * This function should be in put.c, but it knows too much
75 * about the internal structure of the fonts, so it
76 * is here.
77 */
78
79 int M[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
80 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
81 int N[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
82 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
83 int strip[] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff };
84
85
putcode(code,f)86 putcode(code,f)
87 int code; int f; /* character to print */
88 {
89 struct chardata *foundc; /* pointer to found character */
90 char *scanp; /* position to place character in buffer */
91 char *sc; /* real position to place char in buffer */
92 char *cm;
93 int nvpos; /* new vertical position */
94 int nhpos; /* new horizontal position */
95 int nhbyte; /* byte index of horizontal position */
96 int offbit, off8; /* bit offset from byte index of hor. pos.*/
97 double sloffset; /* amount of offset due to slant */
98 int bwidth, cnt; /* width of bitmap in bytes */
99 int h; /* height count */
100 register unsigned int fontdata;
101 unsigned char *to, *from;
102 unsigned int n;
103 int scan_inc;
104
105 if(currentfnt->physical != f || currentfnt->size != size) {
106 currentfnt = findfont(f);
107 }
108 foundc = currentfnt->ch[code];
109 if( foundc == (struct chardata *)0 )
110 return;
111
112 nvpos = PHYS(vpos) - vorigin - foundc->height + foundc->YO;
113 nhpos = PHYS(hpos) + foundc->XO;
114 bwidth = (foundc->width + 7)/BYTE;
115 cm = foundc->cbitmap;
116
117 if((nvpos >= NLINES) || (nvpos + foundc->height <= 0))
118 return;
119 if( nhpos < 0 ) /* ignore chars left of left margin */
120 return;
121
122 /* the following is an ugly optimization: since slant will usually
123 * be zero, and we can save a whole lot of time if that is so,
124 * have a duplicate (faster) loop for that case (DD)
125 */
126
127 if( slant == 0 ) {
128
129 nhbyte = nhpos / BYTE;
130 offbit = nhpos % BYTE;
131 off8 = 8 - offbit;
132 scanp = buf0p + nvpos * BYTES_PER_LINE + nhbyte;
133 scan_inc = BYTES_PER_LINE - bwidth;
134
135 for(h = 0; h < foundc->height; h++) {
136
137 if (scanp + bwidth >= BUFBOTTOM)
138 break;
139
140 cnt = bwidth;
141 if (scanp >= BUFTOP) {
142 do {
143 fontdata = *(unsigned *)cm;
144 cm += 4;
145 if( cnt < 4 )
146 fontdata &= strip[cnt];
147 *(unsigned int *)scanp |= (fontdata >> offbit) & M[off8];
148 scanp++; /* _char_ increment */
149 *(unsigned int *)scanp |= (fontdata << off8) & N[off8];
150 scanp += 3; /* to next _word_ */
151 cnt -= 4;
152 } while( cnt > 0 );
153 }
154 scanp += scan_inc + cnt;
155 cm += cnt;
156 }
157 } else { /* we have to add in a slant offset for each row */
158
159 scanp = buf0p + nvpos * BYTES_PER_LINE;
160 sloffset = slantoffset * (foundc->height - foundc->YO);
161
162 for( h = 0;
163 h < foundc->height;
164 h++, scanp += BYTES_PER_LINE, sloffset -= slantoffset ){
165
166 nhbyte = (nhpos + (int)sloffset) / BYTE;
167 offbit = (nhpos + (int)sloffset) % BYTE;
168 off8 = 8 - offbit;
169 sc = scanp + nhbyte;
170
171 if( sc <= BUFTOP )
172 continue;
173
174 if( sc + bwidth >= BUFBOTTOM )
175 break;
176
177 to = (unsigned char *)sc;
178 from = (unsigned char *)&cm[ h*bwidth ];
179 cnt = bwidth;
180 while (cnt--) {
181 n = *from++;
182 *to++ |= n >> offbit;
183 *to |= n << off8;
184 }
185 }
186 }
187 }
188
189
190
191
192
193 /*
194 * findfont(f): Try to find font f (in current size).
195 * If the font in this size is not already loaded, try to load it.
196 */
197
198
199 struct fontadmin *
findfont(f)200 findfont(f)
201 int f;
202 {
203 struct fontadmin *p = &firstf;
204 char file[BUFSIZ], *fbuf;
205
206
207 DBGPRINT(0, ("Searching for %d size %d\n", f, size ));
208 /*
209 * search list for desired font and size
210 */
211
212 while( p->physical != 0 ) {
213
214 if( p->physical == f && p->size == size )
215 return(p);
216 #ifdef DEBUGABLE
217 else if(p->physical > 10000 || p->physical < 10)
218 error(FATAL, "odd font: %d!\n",p->physical);
219 #endif
220 else
221 p = p->f;
222 }
223
224
225 /*
226 * not in list, so make it
227 */
228
229 p->physical = f;
230 p->size = size;
231 p->f = falloc();
232 p->f->physical = 0;
233
234
235 sprintf(file,"%s/%d/%d", BITS, f, pstab[ size ] );
236 fbuf = getfile(file); /* getfile exits if unsuccessful */
237
238 DBGPRINT(0, ("Loading bitmaps for font %d size %d\n", f, size));
239 loadbits( fbuf, p->ch );
240
241 return( p );
242 }
243
244
245
246 /*
247 * loadbits: reconstruct the linked char list from buf,
248 * and put it into the given array.
249 */
250
251
loadbits(buf,cha)252 loadbits( buf, cha )
253 char *buf;
254 struct chardata *cha[];
255 {
256 struct chardata *firstc, *ch;
257 unsigned offset = 0;
258 int i;
259
260 ch = firstc = (struct chardata *)buf;
261
262 /* note we employ a trick here: we know that all
263 * the addresses (->nextchar and ->cbitmap) are
264 * garbage, yet still the list must have been
265 * terminated with ch->nextchar == 0, so we can
266 * still tell where it was supposed to end.
267 */
268
269 while( ch->nextchar != (struct chardata *)0 )
270 {
271 offset += sizeof( struct chardata );
272 ch->cbitmap = (char *)(buf + offset);
273 offset += ch->nbytes;
274 ch->nextchar = (struct chardata *)(buf + offset);
275
276 ch = ch->nextchar;
277 }
278 /* clean up last one */
279 offset += sizeof( struct chardata );
280 ch->cbitmap = (char *)(buf + offset);
281
282 /*
283 * now go through and fill up the array
284 */
285 ch = firstc;
286 for( i=1; i<=128; i++ )
287 {
288 if( i == ch->charno )
289 {
290 cha[i] = ch;
291 ch = ch->nextchar;
292 }
293 else
294 cha[i] = 0;
295 }
296 }
297
298
299
300 struct fontadmin *
falloc()301 falloc()
302 {
303 register char *p;
304
305 if(( p = malloc(sizeof(struct fontadmin))) == (char *) 0)
306 error(FATAL, "Falloc");
307 return((struct fontadmin *) p);
308 }
309
310
311
312
313 /*
314 * get the contents of the file, and return a pointer to them.
315 * All errors result in death.
316 *
317 */
318
319
320 char *
getfile(file)321 getfile(file)
322 char *file;
323 {
324 struct stat statbuf;
325 char *filebuf, *malloc();
326 int fdi;
327
328 if( stat(file, &statbuf) == -1 )
329 error(FATAL, "Can't get file status: %s (error %d)", file, errno);
330
331 if((statbuf.st_mode & S_IFMT) != S_IFREG)
332 error(FATAL, "File %s not a regular file", file);
333
334 if((fdi = open(file, O_RDONLY)) < 0 )
335 error(FATAL, "Can not open %s (error %d)", file, errno );
336
337 if((filebuf = malloc( (unsigned int)statbuf.st_size )) == (char *)0)
338 error(FATAL, "Not enough room for file %s!", file);
339
340 if(read(fdi, filebuf, (int)statbuf.st_size) != statbuf.st_size)
341 error(FATAL, "Read error on %s", file);
342
343 (void) close( fdi );
344 return( filebuf );
345 }
346