Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * text rendering for the framebuffer console
  3  * pick fonts from X11 font server or
  4  * use linux consolefont psf files.
  5  * (c) 2001 Gerd Knorr <kraxel@bytesex.org>
  6  */
  7 #include "config.h"
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <unistd.h>
 12 #include <string.h>
 13 #include <errno.h>
 14 #include <linux/fb.h>
 15 
 16 #include "fbtools.h"
 17 #include "fs.h"
 18 
 19 /* ------------------------------------------------------------------ */
 20 
 21 #define BIT_ORDER       BitmapFormatBitOrderMSB
 22 #ifdef BYTE_ORDER
 23 #undef BYTE_ORDER
 24 #endif
 25 #define BYTE_ORDER      BitmapFormatByteOrderMSB
 26 #define SCANLINE_UNIT   BitmapFormatScanlineUnit8
 27 #define SCANLINE_PAD    BitmapFormatScanlinePad8
 28 #define EXTENTS         BitmapFormatImageRectMin
 29 
 30 #define SCANLINE_PAD_BYTES 1
 31 #define GLWIDTHBYTESPADDED(bits, nBytes)                                    \
 32         ((nBytes) == 1 ? (((bits)  +  7) >> 3)          /* pad to 1 byte  */\
 33         :(nBytes) == 2 ? ((((bits) + 15) >> 3) & ~1)    /* pad to 2 bytes */\
 34         :(nBytes) == 4 ? ((((bits) + 31) >> 3) & ~3)    /* pad to 4 bytes */\
 35         :(nBytes) == 8 ? ((((bits) + 63) >> 3) & ~7)    /* pad to 8 bytes */\
 36         : 0)
 37 
 38 static const unsigned fs_masktab[] = {
 39     (1 << 7), (1 << 6), (1 << 5), (1 << 4),
 40     (1 << 3), (1 << 2), (1 << 1), (1 << 0),
 41 };
 42 
 43 /* ------------------------------------------------------------------ */
 44 
 45 #ifndef X_DISPLAY_MISSING
 46 static FSServer           *svr;
 47 #endif
 48 static unsigned int       bpp,black,white;
 49 
 50 static void (*setpixel)(void *ptr, unsigned int color);
 51 
 52 static void setpixel1(void *ptr, unsigned int color)
 53 {
 54     unsigned char *p = ptr;
 55     *p = color;
 56 }
 57 static void setpixel2(void *ptr, unsigned int color)
 58 {
 59     unsigned short *p = ptr;
 60     *p = color;
 61 }
 62 static void setpixel3(void *ptr, unsigned int color)
 63 {
 64     unsigned char *p = ptr;
 65     *(p++) = (color >> 16) & 0xff;
 66     *(p++) = (color >>  8) & 0xff;
 67     *(p++) =  color        & 0xff;
 68 }
 69 static void setpixel4(void *ptr, unsigned int color)
 70 {
 71     unsigned long *p = ptr;
 72     *p = color;
 73 }
 74 
 75 int fs_init_fb(int white8)
 76 {
 77     switch (fb_var.bits_per_pixel) {
 78     case 8:
 79         white = white8; black = 0; bpp = 1;
 80         setpixel = setpixel1;
 81         break;
 82     case 15:
 83     case 16:
 84         if (fb_var.green.length == 6)
 85             white = 0xffff;
 86         else
 87             white = 0x7fff;
 88         black = 0; bpp = 2;
 89         setpixel = setpixel2;
 90         break;
 91     case 24:
 92         white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;
 93         setpixel = setpixel3;
 94         break;
 95     case 32:
 96         white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;
 97         setpixel = setpixel4;
 98         break;
 99     default:
100         fprintf(stderr, "Oops: %i bit/pixel ???\n",
101                 fb_var.bits_per_pixel);
102         return -1;
103     }
104     return 0;
105 }
106 
107 void fs_render_fb(unsigned char *ptr, int pitch,
108                   FSXCharInfo *charInfo, unsigned char *data)
109 {
110     int row,bit,bpr,x;
111 
112     bpr = GLWIDTHBYTESPADDED((charInfo->right - charInfo->left),
113                              SCANLINE_PAD_BYTES);
114     for (row = 0; row < (charInfo->ascent + charInfo->descent); row++) {
115         for (x = 0, bit = 0; bit < (charInfo->right - charInfo->left); bit++) {
116             if (data[bit>>3] & fs_masktab[bit&7])
117                 setpixel(ptr+x,white);
118             x += bpp;
119         }
120         data += bpr;
121         ptr += pitch;
122     }
123 }
124 
125 int fs_puts(struct fs_font *f, unsigned int x, unsigned int y,
126             unsigned char *str)
127 {
128     unsigned char *pos,*start;
129     int i,c,j,w;
130 
131     pos  = fb_mem+fb_mem_offset;
132     pos += fb_fix.line_length * y;
133     for (i = 0; str[i] != '\0'; i++) {
134         c = str[i];
135         if (NULL == f->eindex[c])
136             continue;
137         /* clear with bg color */
138         start = pos + x*bpp + f->fontHeader.max_bounds.descent * fb_fix.line_length;
139         w = (f->eindex[c]->width+1)*bpp;
140         for (j = 0; j < f->height; j++) {
141             memset(start,0,w);
142             start += fb_fix.line_length;
143         }
144         /* draw char */
145         start = pos + x*bpp + fb_fix.line_length * (f->height-f->eindex[c]->ascent);
146         fs_render_fb(start,fb_fix.line_length,f->eindex[c],f->gindex[c]);
147         x += f->eindex[c]->width;
148         if (x > fb_var.xres - f->width)
149             return -1;
150     }
151     return x;
152 }
153 
154 int fs_textwidth(struct fs_font *f, unsigned char *str)
155 {
156     int width = 0;
157     int i,c;
158     
159     for (i = 0; str[i] != '\0'; i++) {
160         c = str[i];
161         if (NULL == f->eindex[c])
162             continue;
163         width += f->eindex[c]->width;
164     }
165     return width;
166 }
167 
168 void fs_render_tty(FSXCharInfo *charInfo, unsigned char *data)
169 {
170     int bpr,row,bit,on;
171 
172     bpr = GLWIDTHBYTESPADDED((charInfo->right - charInfo->left),
173                              SCANLINE_PAD_BYTES);
174     for (row = 0; row < (charInfo->ascent + charInfo->descent); row++) {
175         fprintf(stdout,"|");
176         for (bit = 0; bit < (charInfo->right - charInfo->left); bit++) {
177             on = data[bit>>3] & fs_masktab[bit&7];
178             fprintf(stdout,"%s",on ? "##" : "  ");
179         }
180         fprintf(stdout,"|\n");
181         data += bpr;
182     }
183     fprintf(stdout,"--\n");
184 }
185 
186 /* ------------------------------------------------------------------ */
187 
188 #ifndef X_DISPLAY_MISSING
189 /* connect to font server */
190 int fs_connect(char *servername)
191 {
192     if (NULL == servername)
193         servername = getenv("FONTSERVER");
194     if (NULL == servername)
195         servername = "unix/:7100";
196     svr = FSOpenServer(servername);
197     if (NULL == svr) {
198         if (NULL == FSServerName(servername)) {
199             fprintf(stderr, "no font server defined\n");
200         } else {
201             fprintf(stderr, "unable to open server \"%s\"\n",
202                     FSServerName(servername));
203         }
204         return -1;
205     }
206     return 0;
207 }
208 
209 /* load font from font server */
210 struct fs_font* fs_open(char *pattern)
211 {
212     int              nnames = 1;
213     int              available,high,low,encoding,bpr;
214     char             **fonts;
215     unsigned char    *glyph;
216     Font             dummy;
217     FSBitmapFormat   format;
218     FSXCharInfo      *charInfo;
219     struct fs_font   *f = NULL;
220     
221     if (NULL == svr) {
222         fprintf(stderr,"fs: not connected\n");
223         return NULL;
224     }
225 
226     fonts = FSListFonts(svr, pattern, nnames, &available);
227     if (0 == available) {
228         fprintf(stderr,"fs: font not available [%s]\n",pattern);
229         goto out;
230     }
231     fprintf(stderr,"using x11 font \"%s\"\n",fonts[0]);
232 
233     f = malloc(sizeof(*f));
234     memset(f,0,sizeof(*f));
235     f->font = FSOpenBitmapFont(svr, 0, 0, fonts[0], &dummy);
236     FSFreeFontNames(fonts);
237     if (0 == f->font)
238         goto out;
239     
240     FSQueryXInfo(svr,f->font,&f->fontHeader, &f->propInfo,
241                  &f->propOffsets, &f->propData);
242     format = BYTE_ORDER | BIT_ORDER | SCANLINE_UNIT | SCANLINE_PAD | EXTENTS;
243     FSQueryXExtents16(svr, f->font, True, (FSChar2b *) 0, 0, &f->extents);
244     FSQueryXBitmaps16(svr, f->font, format, True, (FSChar2b *) 0, 0,
245                       &f->offsets, &f->glyphs);
246 
247     f->maxenc = (f->fontHeader.char_range.max_char.high+1) << 8;
248     f->width  = f->fontHeader.max_bounds.right - f->fontHeader.min_bounds.left;
249     f->height = f->fontHeader.max_bounds.ascent + f->fontHeader.max_bounds.descent;
250     f->eindex = malloc(f->maxenc * sizeof(FSXCharInfo*));
251     f->gindex = malloc(f->maxenc * sizeof(unsigned char*));
252     memset(f->eindex,0,f->maxenc * sizeof(FSXCharInfo*));
253     memset(f->gindex,0,f->maxenc * sizeof(unsigned char*));
254 
255     glyph    = f->glyphs;
256     charInfo = f->extents;
257     for (high  = f->fontHeader.char_range.min_char.high;
258          high <= f->fontHeader.char_range.max_char.high;
259          high++) {
260         for (low  = f->fontHeader.char_range.min_char.low;
261              low <= f->fontHeader.char_range.max_char.low;
262              low++) {
263             bpr = GLWIDTHBYTESPADDED((charInfo->right - charInfo->left),
264                                      SCANLINE_PAD_BYTES);
265             encoding = (high<<8) + low;
266 #ifdef TTY
267             fprintf(stdout,"e=0x%x | w=%d  l=%d r=%d  |  a=%d d=%d\n",
268                     encoding,charInfo->width,charInfo->left,
269                     charInfo->right,charInfo->ascent,charInfo->descent);
270 #endif
271             if ((charInfo->width != 0) || (charInfo->right != charInfo->left)) {
272                 f->gindex[encoding] = glyph;
273                 f->eindex[encoding] = charInfo;
274 #ifdef TTY
275                 fs_render_tty(f->eindex[encoding],
276                               f->gindex[encoding]);
277 #endif
278             }
279             glyph += (charInfo->descent + charInfo->ascent) * bpr;
280             charInfo++;
281         }
282     }
283     return f;
284 
285  out:
286     if (f) 
287         fs_free(f);
288     return NULL;
289 }
290 #endif
291 
292 void fs_free(struct fs_font *f)
293 {
294     if (f->gindex)
295         free(f->gindex);
296 #if 0
297     if (f->extents)
298         FSFree((char *) f->extents);
299     if (f->offsets)
300         FSFree((char *) f->offsets);
301     if (f->propOffsets)
302         FSFree((char *) (f->propOffsets));
303     if (f->propData)
304         FSFree((char *) (f->propData));
305 #endif
306 #if 0 /* FIXME */
307     if (f->glyphs)
308         FSFree((char *) f->glyphs);
309 #endif
310     free(f);
311 }
312 
313 /* ------------------------------------------------------------------ */
314 /* load console font file                                             */
315 
316 static char *default_font[] = {
317     /* why the heck every f*cking distribution picks another
318        location for these fonts ??? */
319     "/usr/share/consolefonts/lat1-16.psf",
320     "/usr/share/consolefonts/lat1-16.psf.gz",
321     "/usr/share/consolefonts/lat1-16.psfu.gz",
322     "/usr/share/kbd/consolefonts/lat1-16.psf",
323     "/usr/share/kbd/consolefonts/lat1-16.psf.gz",
324     "/usr/share/kbd/consolefonts/lat1-16.psfu.gz",
325     "/usr/lib/kbd/consolefonts/lat1-16.psf",
326     "/usr/lib/kbd/consolefonts/lat1-16.psf.gz",
327     "/usr/lib/kbd/consolefonts/lat1-16.psfu.gz",
328     "/lib/kbd/consolefonts/lat1-16.psf",
329     "/lib/kbd/consolefonts/lat1-16.psf.gz",
330     "/lib/kbd/consolefonts/lat1-16.psfu.gz",
331     NULL
332 };
333 
334 struct fs_font* fs_consolefont(char **filename)
335 {
336     int  i;
337     char *h,command[256];
338     struct fs_font *f = NULL;
339     FILE *fp;
340 
341     if (NULL == filename)
342         filename = default_font;
343 
344     for(i = 0; filename[i] != NULL; i++) {
345         if (-1 == access(filename[i],R_OK))
346             continue;
347         break;
348     }
349     if (NULL == filename[i]) {
350         fprintf(stderr,"can't find console font file\n");
351         return NULL;
352     }
353 
354     h = filename[i]+strlen(filename[i])-3;
355     if (0 == strcmp(h,".gz")) {
356         sprintf(command,"zcat %s",filename[i]);
357         fp = popen(command,"r");
358     } else {
359         fp = fopen(filename[i], "r");
360     }
361     if (NULL == fp) {
362         fprintf(stderr,"can't open %s: %s\n",filename[i],strerror(errno));
363         return NULL;
364     }
365 
366     if (fgetc(fp) != 0x36 ||
367         fgetc(fp) != 0x04) {
368         fprintf(stderr,"can't use font %s\n",filename[i]);
369         return NULL;
370     }
371     fprintf(stderr,"using linux console font \"%s\"\n",filename[i]);
372 
373     f = malloc(sizeof(*f));
374     memset(f,0,sizeof(*f));
375 
376     fgetc(fp);
377     f->maxenc = 256;
378     f->width  = 8;
379     f->height = fgetc(fp);
380     f->fontHeader.min_bounds.left    = 0;
381     f->fontHeader.max_bounds.right   = f->width;
382     f->fontHeader.max_bounds.descent = 0;
383     f->fontHeader.max_bounds.ascent  = f->height;
384 
385     f->glyphs  = malloc(f->height * 256);
386     f->extents = malloc(sizeof(FSXCharInfo)*256);
387     fread(f->glyphs, 256, f->height, fp);
388     fclose(fp);
389 
390     f->eindex  = malloc(sizeof(FSXCharInfo*)   * 256);
391     f->gindex  = malloc(sizeof(unsigned char*) * 256);
392     for (i = 0; i < 256; i++) {
393         f->eindex[i] = f->extents +i;
394         f->gindex[i] = f->glyphs  +i * f->height;
395         f->eindex[i]->left    = 0;
396         f->eindex[i]->right   = 7;
397         f->eindex[i]->width   = 8;
398         f->eindex[i]->descent = 0;
399         f->eindex[i]->ascent  = f->height;
400     }
401     return f;
402 }
403 
404 
405 #ifdef TESTING
406 /* ------------------------------------------------------------------ */
407 /* for testing                                                        */
408 
409 int debug;
410 
411 /* list fonts */
412 int fs_ls(char *pattern)
413 {
414     int    nnames = 16;
415     int    available,i;
416     char   **fonts;
417 
418     if (NULL == svr) {
419         fprintf(stderr,"fs: not connected\n");
420         return -1;
421     }
422 
423     fonts = FSListFonts(svr, pattern, nnames, &available);
424     while (nnames <= available) {
425         nnames *= 2;
426         FSFreeFontNames(fonts);
427         fonts = FSListFonts(svr, pattern, nnames, &available);
428     }
429     for (i = 0; i < available; i++) {
430         fprintf(stderr,"%s\n",fonts[i]);
431     }
432     FSFreeFontNames(fonts);
433     return 0;
434 }
435 
436 void dump_charset(struct fs_font *f)
437 {
438     unsigned char *pos;
439     int c,x,y;
440 
441     x = 0, y = 0;
442     for (c = 0; c < f->maxenc; c++) {
443         if (NULL == f->eindex[c])
444             continue;
445         pos  = fb_mem+fb_mem_offset;
446         pos += fb_fix.line_length * (y+f->height-f->eindex[c]->ascent);
447         pos += x*bpp;
448         fs_render_fb(pos,fb_fix.line_length,f->eindex[c],f->gindex[c]);
449         x += f->eindex[c]->right-f->eindex[c]->left+1;
450         if (x > fb_var.xres - f->width) {
451             x = 0;
452             y += f->height+1;
453         }
454         if (y > fb_var.yres - f->height)
455             break;
456     }
457 }
458 
459 int main(int argc, char *argv[])
460 {
461     struct fs_font *f = NULL;
462     unsigned char dummy[42];
463     int fd;
464 
465     if (argc < 2) {
466         fprintf(stderr,"missing arg\n");
467         exit(1);
468     }
469 
470     /* try font server */
471     if (-1 != fs_connect(NULL)) {
472         fs_ls(argv[1]);
473         f = fs_open(argv[1]);
474         if (NULL == f)
475             fprintf(stderr,"no such font\n");
476     }
477 
478     /* try console font */
479     if (NULL == f)
480         f = fs_consolefont(NULL);
481     if (NULL == f)
482         exit(1);
483         
484 #ifdef TTY
485     exit(1);
486 #endif
487 
488     fd = fb_init(NULL, NULL, 0);
489     fb_cleanup_fork();
490     fb_switch_init();
491     fs_init_fb();
492 
493     if (argc < 3) {
494         dump_charset(f);
495     } else {
496         fs_puts(f,0,0,argv[2]);
497     }
498     fgets(dummy,42,stdin);
499     
500     return 0;
501 }
502 #endif
503 
  This page was automatically generated by the LXR engine.