Trying to figure out how to render a single character represented by a FT_Bitmap in X

joe M joe9mail at gmail.com
Sat Feb 16 19:34:33 PST 2013


> Thanks a lot for your very informative comments. They were very
> helpful. I am trying to get a working program based on your comments.
> I will email it to the list once I have a working version.

For the record, a sample program to write out the Char 'I' to X:

#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <ft2build.h>
#include FT_FREETYPE_H

#define WIDTH   32
#define HEIGHT  40

/* origin is the upper left corner */
unsigned char image[HEIGHT][WIDTH];
unsigned char pixmap[(WIDTH/8)*HEIGHT];

/* Replace this function with something useful. */
void draw_bitmap( FT_Bitmap*  bitmap, FT_Int pitch, FT_Int left, FT_Int top) {
   int h, w, bitpos, bytepos, row, bitmapw;
   char byte ;
   int twidth = left + bitmap->width;

   /* blank out above the top to the max height */
   for (h = 0; h < (HEIGHT - top); h++) {
      for (w = 0; w < twidth; w++) {
         image[h][w] = 0;
      }
   }

   for (h = (HEIGHT - top); h < HEIGHT; h++) {
      row = pitch * (h - (HEIGHT - top));
      for (w = 0; w < twidth; w++) {
         if (w < left) {
            image[h][w] = 0;
         } else {
            bitmapw = w-left;
            bytepos = bitmapw / 8;
            /* as bits are laid out from high bit to the low bit */
            bitpos  = 7 - (bitmapw % 8);
            byte    = (char) (bitmap->buffer[row+bytepos]);
            /* If you want the k-th bit of n, then do  */
            /*    (n & ( 1 << k )) >> k */
            image[h][w] = (byte & ( 1 << bitpos )) >> bitpos;
            /* if (12 == row) fprintf(stdout,
            "w: %02x, bitmapw: %02x, byte: %02x, bitpos: %02x, image: %01x ",
             w,bitmapw,byte,bitpos,image[w][h]); */
         }
      }
   }
}

void show_image( int width ) {
  int  h, w;

  for ( h = 0; h < HEIGHT; h++ ) {
   fprintf(stdout,"row: %02d",h);
    for ( w = 0; w < width; w++ )
      putchar( image[h][w] == 0 ? ' ' : '.' );
    putchar( '\n' );
  }
}

void to_xpixmap( int width ) {
  int  h, w;

  for ( h = 0; h < HEIGHT; h++ ) {
      for ( w = 0; w < (width/8); w++ ) {
         pixmap[(h*(width/8))+w] =
                        (image[h][((w*8)+7)]<<7) |
                        (image[h][((w*8)+6)]<<6) |
                        (image[h][((w*8)+5)]<<5) |
                        (image[h][((w*8)+4)]<<4) |
                        (image[h][((w*8)+3)]<<3) |
                        (image[h][((w*8)+2)]<<2) |
                        (image[h][((w*8)+1)]<<1) |
                        (image[h][((w*8)+0)]<<0) ;
         /* fprintf(stdout,"w: %02d, h: %02d -- %02x\n", */
         /*                w,h,pixmap[(h*(width/8))+w]); */
      }
   }
}


int main( int     argc, char**  argv ) {
  FT_Library    library;
  FT_Face       face;

  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;
  int pitch;
  unsigned char *bitmap;
   int h,wi;
   int twidth = 0;

   Display *d;
   Window w;
   XEvent e;
   int s,i;
   Pixmap p;
    unsigned int bwidth, bheight;
    int hotspot_x, hotspot_y;
  /* int           target_height; */
  int           n, num_chars;
   char *msg = "Hello, World!";

   error = FT_Init_FreeType( &library );              /* initialize library */
   /* error handling omitted */

   error = FT_New_Face(
            library,
            "/usr/share/fonts/liberation-fonts/LiberationMono-Regular.ttf",
            0, &face );/* create face object */
   /* error handling omitted */

   FT_Set_Pixel_Sizes(face, 0, 48);

   error = FT_Load_Char( face, 'I', FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
   if (0 != error) {
   fprintf(stderr,"could not load FT_Load_Char\n");
   fflush(stderr);
      exit(1);
   }
   slot = face->glyph;
   fprintf(stdout,"returned bitmap characterstics:\n \
         bitmap_left: %d,\n\
         bitmap_top: %d,\n\
            rows: %d, \n\
            width: %d, \n\
            pitch: %d, \n\
            num_grays: %d, \n\
            pixel_mode: %d\n",
            slot->bitmap_left,
            slot->bitmap_top,
            slot->bitmap.rows,
            slot->bitmap.width,
            slot->bitmap.pitch,
            slot->bitmap.num_grays,
            slot->bitmap.pixel_mode);
  /* if ( pitch < 0 ) pitch = -pitch; */
  /* bitmap = (unsigned char *) malloc(slot->bitmap.rows * pitch); */
  /* memcpy(bitmap, slot->bitmap.buffer, pitch*slot->bitmap.rows ); */
  /* fprintf(stdout,"pitch: %d, rows: %d, pitch * slot->bitmap.rows: %d\n", */
  /*                    pitch, */
  /*                    slot->bitmap.rows, */
  /*                    pitch * slot->bitmap.rows); */
  for(i = 0; i < slot->bitmap.pitch * slot->bitmap.rows; i++) {
      if (0 == i % slot->bitmap.pitch) fprintf(stdout,"\n");
      fprintf(stdout,"%d: 0x%02X ", i,slot->bitmap.buffer[i]);
      fflush(stdout);
   }
  fprintf(stdout,"\n");

  /* now, draw to our target surface (convert position) */
  draw_bitmap( &slot->bitmap,
                 slot->bitmap.pitch,
                 slot->bitmap_left,
                 slot->bitmap_top );
  twidth = (slot->bitmap_left+slot->bitmap.width);
  show_image(twidth);
  to_xpixmap(twidth);
  fprintf(stdout,"\n");
  fflush(stdout);


  FT_Done_Face    ( face );
  FT_Done_FreeType( library );

   d = XOpenDisplay(NULL);
   if (d == NULL) {
      fprintf(stderr, "Cannot open display\n");
      exit(1);
   }

   s = DefaultScreen(d);
   w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
                           BlackPixel(d, s), WhitePixel(d, s));
   XSelectInput(d, w, ExposureMask | KeyPressMask);
   XMapWindow(d, w);

   while (1) {
      XNextEvent(d, &e);
      if (e.type == Expose) {
            XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
            XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
            XDrawPoint(d, w, DefaultGC(d,s), 30, 30);
            XSync(d, False);
            usleep(100000);

            p = XCreateBitmapFromData(d, w, (unsigned char *) pixmap ,
                                        twidth ,
                                        (unsigned int) HEIGHT);
            XWriteBitmapFile(d,"test.xbm",p,twidth,HEIGHT,0,0);
            XCopyPlane(d, p , w, DefaultGC(d,s),
                        0, 0,
                        twidth, HEIGHT,
                        40, 40,1);
            XSync(d, False);
            usleep(100000);
      }
      if (e.type == KeyPress) break;
   }

   XCloseDisplay(d);
  return 0;
}


More information about the xorg mailing list