From: Roger L. <rl...@wh...> - 2005-06-27 20:52:14
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi folks, I'm looking into writing a program which will use the framebuffer to display rendered fonts and some graphics. However, I've not yet found much in the way of programming documentation. Is there anything you would recommend? (I've looked at SDL, directfb and GGI sources, but they are very complex.) Using the comments in <linux/fb.h> and some simple examples I found, I've written the sample code below. However, none of the examples I saw made any use of the fb_bitfield information. I ran into problems when I tried my (i386 tested) code on a PPC. After fixing the code, it still doesn't work. I have the bizarre situation that if I run it under X11 (using XF86_FBDev), I see the glyphs rendered fine, but if I run it on the console the colours are mucked up, and I can't see any change in the bitfield data. Are there any examples of painting simple RGB pixel data onto any arbitrary framebuffer device which also works on big and little endian systems. I'm sure this is fairly simple once you know how! Additionally, is there any documentation about how colourmaps and the other framebuffer features work? Many thanks, Roger This program simply renders each ASCII character in turn and paints it. You might need to change the fb device and font path. It's currently hard-coded for RBG LCDs, but is simple to change for a CRT. Compile with c99 -o ft-lcd ft-lcd.c `freetype-config --cflags --libs` #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <ft2build.h> #include FT_FREETYPE_H void fail (const char *reason) { fprintf (stderr, "%s\n", reason); exit (EXIT_FAILURE); } int main() { int fbfd = 0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; char *fbp = 0; int x = 0, y = 0; long int location = 0; // Open the file for reading and writing fbfd = open("/dev/fb/0", O_RDWR); if (fbfd < 0) fail("Error: cannot open framebuffer device."); // Get fixed screen information if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) fail("Error reading fixed information."); // Get variable screen information if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) fail("Error reading variable information."); printf("%ux%u (%ux%u), %ubpp\n", vinfo.xres, vinfo.yres, vinfo.xres_virtual, vinfo.yres_virtual, vinfo.bits_per_pixel ); printf("offsets: x=%u, y=%u\n", vinfo.xoffset, vinfo.yoffset); printf("red: o=%u, l=%u, mr=%u\n", vinfo.red.offset, vinfo.red.length, vinfo.red.msb_right); printf("green: o=%u, l=%u, mr=%u\n", vinfo.green.offset, vinfo.green.length, vinfo.green.msb_right); printf("blue: o=%u, l=%u, mr=%u\n", vinfo.blue.offset, vinfo.blue.length, vinfo.blue.msb_right); printf("transp: o=%u, l=%u, mr=%u\n", vinfo.transp.offset, vinfo.transp.length, vinfo.transp.msb_right); unsigned int red_max = 1 << vinfo.red.length; unsigned int green_max = 1 << vinfo.green.length; unsigned int blue_max = 1 << vinfo.blue.length; unsigned int transp_max = 1 << vinfo.transp.length; unsigned int red_mask = 0; for (unsigned int i=0; i<vinfo.red.length; ++i) red_mask |= 1 << (vinfo.red.offset + i); unsigned int green_mask = 0; for (unsigned int i=0; i<vinfo.green.length; ++i) green_mask |= 1 << (vinfo.green.offset + i); unsigned int blue_mask = 0; for (unsigned int i=0; i<vinfo.blue.length; ++i) blue_mask |= 1 << (vinfo.blue.offset + i); unsigned int transp_mask = 0; for (unsigned int i=0; i<vinfo.transp.length; ++i) transp_mask |= 1 << (vinfo.transp.offset + i); // Figure out the size of the screen in bytes screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; // Map the device to memory fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int)fbp == -1) fail("Error: failed to map framebuffer device to memory.\n"); // Now setup FreeType FT_Library library; FT_Face face; int error = FT_Init_FreeType( &library ); if ( error ) { fail ("Failed to initialise FreeType"); } error = FT_New_Face( library, "/usr/share/fonts/truetype/ttf-bitstream-vera/VeraMono.ttf", 0, &face ); if ( error == FT_Err_Unknown_File_Format ) { fail ("Unsupported font format"); } else if ( error ) { fail ("Error reading font file"); } error = FT_Set_Char_Size ( face, 0, 12 * 64, 100, 100 ); if (error) { fail ("Error setting char size"); } // Display each ASCII printable char for (FT_ULong n = 33; n < 127; ++n) { FT_UInt glyph_index = FT_Get_Char_Index (face, n); FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_TARGET_LCD); error = FT_Render_Glyph (face->glyph, FT_RENDER_MODE_LCD); if (error) { fail ("Error rendering glyph"); } if (n == '_') continue; FT_Bitmap *bitmap = &face->glyph->bitmap; // printf ("Glyph '%c': %d * %d\n", (char) n, bitmap->width, bitmap->rows); //printf ("Bitmap top: %d\nBitmap left: %d\n", face->glyph->bitmap_top, // face->glyph->bitmap_left); for (y=0; y<200; ++y) for (x=0; x<200; ++x) { location = ((x + 0)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((y + 0)+vinfo.yoffset) * finfo.line_length; if ( vinfo.bits_per_pixel == 32 ) { unsigned int *pixel = (int *) (fbp + location); *pixel = 0; } } for (y=0; y<bitmap->rows; ++y) for (x=0; x< (bitmap->width / 3); ++x) { location = ((x + face->glyph->bitmap_left)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((y + face->glyph->bitmap_top)+vinfo.yoffset) * finfo.line_length; unsigned int r = *(bitmap->buffer + (y * bitmap->pitch) + (x*3 + 0)); // r *= (red_max /8); unsigned int g = *(bitmap->buffer + (y * bitmap->pitch) + (x*3 + 1)); // g *= (red_max /8); unsigned int b = *(bitmap->buffer + (y * bitmap->pitch) + (x*3 + 2)); // b *= (red_max /8); // printf("r=%u, g=%u, b=%u\n", r, g, b); if ( vinfo.bits_per_pixel == 32 ) { unsigned int *pixel = (int *) (fbp + location); *pixel = 0; // This works when I run under X11_FBDev (i.e. the // colours are correct), but if I run on the console, I // get a mess and mostly blue colours... *pixel |= ((r << vinfo.red.offset) & red_mask); *pixel |= ((g << vinfo.green.offset) & green_mask); *pixel |= ((r << vinfo.blue.offset) & blue_mask); } } sleep (1); } return 0; } - -- Roger Leigh Printing on GNU/Linux? http://gimp-print.sourceforge.net/ Debian GNU/Linux http://www.debian.org/ GPG Public Key: 0x25BFB848. Please sign and encrypt your mail. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/> iD8DBQFCwGWTVcFcaSW/uEgRAkt1AJ9n98Nx0sFOCSQz6FKJ4mftcnijLACgiW6A Ew9wJRanhXh419I9x6PRgzU= =2YCz -----END PGP SIGNATURE----- |