数码相框——矢量字体原理(7)

时间:2022-09-05 16:13:15

这一节,主要实现在LCD的居中显示两行字符

来源:http://liu1227787871.blog.163.com/blog/static/2053631972012628101423971/

代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
//#include <sys/types.h>
//#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/fb.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H
 #include FT_GLYPH_H

int fd_fb = 0;
struct fb_var_screeninfo  fb_var;
struct fb_fix_screeninfo   fb_fix;
int screen_size = 0;
unsigned char* fb_mem;
int line_width;
int  pix_width;
 typedef struct TGlyph_ {
     FT_UInt index; /* glyph index */
    FT_Vector pos; /* glyph origin on the baseline */
    FT_Glyph image; /* glyph image */
} TGlyph, *PGlyph;

 #define MAX_GLYPHS 100
void lcd_put_pixel(int x, int y, unsigned int color)
{
    unsigned char *pen_8 = (unsigned char*)(fb_mem+y*line_width+x*pix_width);
    unsigned short *pen_16;
    unsigned int *pen_32;
    pen_16 = (unsigned short*)pen_8;
    pen_32 = (unsigned int*)pen_8;
    unsigned char red,green,blue;
    switch(fb_var.bits_per_pixel)
    {
        case 8:
            *pen_8 = color;
            break;
        case 16:
            red = (color >>16)&0xff;
            green = (color>>8)&0xff;
            blue = (color>>0)&0xff;
            color = ((red>>3)<<11)|((green>>2)<<5)|((blue>>3)<<0);
            *pen_16 = color;
            break;
        case 32:
            *pen_32 = color;
            break;
        default:
            printf("Can' support  error\n");
            break;

    }
    

}


/* Replace this function with something useful. */

void
draw_bitmap( FT_Bitmap*  bitmap,
             FT_Int      x,
             FT_Int      y)
{
  FT_Int  i, j, p, q;
  FT_Int  x_max = x + bitmap->width;
  FT_Int  y_max = y + bitmap->rows;

  for ( i = x, p = 0; i < x_max; i++, p++ )
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
      if ( i < 0      || j < 0       ||
           i >= fb_var.xres|| j >= fb_var.yres)
        continue;
    lcd_put_pixel(i,j, bitmap->buffer[q * bitmap->width + p]);
    }
  }
}

int Get_Glyphs_Frm_Wstr(FT_Face face, wchar_t* wstr, TGlyph glyphs[] )
{
    int n;
    PGlyph glyph = glyphs;
     int pen_x = 0;
    int pen_y = 0;
    int error;
     FT_GlyphSlot  slot =face->glyph;
    for(n=0;n<wcslen(wstr);n++)
    {
        /*¸ù¾Ýunicode±àÂë»ñµÃglyphË÷Òý*/
        glyph->index = FT_Get_Char_Index( face, wstr[n] );    
         glyph->pos.x = pen_x;
         glyph->pos.y = pen_y;
         /*¸ù¾ÝË÷Òý»ñµÃglyph£¬²¢½«glyph´æ·ÅÔÚface->glyph*/
          error = FT_Load_Glyph( face, glyph->index, FT_LOAD_DEFAULT );
          if ( error )
              continue;
          /*  ½«face->glyphÌáÈ¡³öÀ´´æ·ÅÔÚglyph->imageÀïÃæ*/
           error = FT_Get_Glyph( face->glyph, &glyph->image);
           if ( error )
               continue;
           /* translate the glyph image now */
           /*½«glyphµÄλÖ÷ÅÔÚglyph->imageÖÐ*/
           FT_Glyph_Transform( glyph->image, 0, &glyph->pos);

            pen_x += slot->advance.x; /* 1/64 point */
         /* increment number of glyphs */
         glyph++;
    }
     /* count number of glyphs loaded */
    return  (glyph - glyphs);
}
 void compute_string_bbox( TGlyph glyphs[],FT_UInt num_glyphs, FT_BBox *abbox )
 {
     FT_BBox bbox;
     int n;
     bbox.xMin = bbox.yMin = 32000;
     bbox.xMax = bbox.yMax = -32000;
     for ( n = 0; n < num_glyphs; n++ )    
     {
         FT_BBox glyph_bbox;
         /*¸ù¾Ýglyphs[n].image»ñµÃ±ß½çÐÅÏ¢²¢´æ·ÅÔÚglyph_bboxÖÐ*/
          FT_Glyph_Get_CBox(glyphs[n].image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox );
         if(glyph_bbox.xMin < bbox.xMin)
             bbox.xMin = glyph_bbox.xMin;
        
         if(glyph_bbox.xMax > bbox.xMax)
             bbox.xMax = glyph_bbox.xMax;

          if(glyph_bbox.yMin < bbox.yMin)
             bbox.yMin = glyph_bbox.yMin;

          if(glyph_bbox.yMax > bbox.yMax)
             bbox.yMax = glyph_bbox.yMax;  
     }
     /*·µ»Øbbox*/
     *abbox = bbox;

 }
void  Draw_Glyphs(TGlyph glyphs[], FT_UInt num_glyphs,  FT_Vector pen)
{
    int n;
    int error;
    for(n=0;n<num_glyphs;n++)
    {
        /*¼Ç¼ԭµãÐÅÏ¢*/
        FT_Glyph_Transform( glyphs[n].image, 0, &pen);
         /* convert glyph image to bitmap (destroy the glyph copy!) */
         /*/ ʸÁ¿Í¼×ª»»ÎªÎ»Í¼ÒÔ±ãÏÔʾ*/
         error = FT_Glyph_To_Bitmap( &glyphs[n].image, FT_RENDER_MODE_NORMAL, 0, /* no additional translation */ 1 );
         if(!error)
         {
             /*Ç¿Öƽ«glyphs[n].imageת»»ÎªFT_BitmapGlyph ÀàÐ͵ÄÊý¾Ý*/
            FT_BitmapGlyph bit = (FT_BitmapGlyph) glyphs[n].image;    
            draw_bitmap( &bit->bitmap, bit->left, fb_var.yres- bit->top );
            FT_Done_Glyph( glyphs[n].image);
         }         
    }
}
int main(int argc,char ** argv)
{
     FT_Library    library;
  FT_Face       face;


  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;
    double        angle;
FT_BBox          bbox;
//   FT_Glyph      glyph;
int           target_height;
int        n;
int         line_ymax = 0;
int        line_ymin =320;
  wchar_t *wstr1 = L"hello嵌入式g";
 wchar_t *wstr2 = L"www.100ask.com";
 
  TGlyph glyphs[MAX_GLYPHS]; /* glyphs table */
  FT_UInt num_glyphs;
  int line_box_width;
  int line_box_height;
 
    fd_fb = open("/dev/fb0",O_RDWR);
    if(fd_fb < 0)
    {
        printf("open /dev/fb0 failed\n");
        return -1;
    }
    
    if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &fb_var))
    {
        printf("get var information failed\n");
        return -1;
    }
    if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fb_fix))
    {
        printf("get fix information failed\n");
        return -1;
    }
    screen_size = fb_var.xres * fb_var.yres * fb_var.bits_per_pixel /8;
    line_width = fb_var.xres * fb_var.bits_per_pixel /8;
    pix_width = fb_var.bits_per_pixel /8;
    fb_mem =(unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if(fb_mem == (unsigned char *)-1)
    {
        printf("fb_mem mmap failed\n ");
        return -1;
    }
    memset(fb_mem, 0, screen_size);
    /*Ôö¼ÓFreetype*/
    if(argc != 2)
    {
        printf("Useage: %s <font file>\n",argv[0]);
        return -1;
    }
    error = FT_Init_FreeType( &library );              /* initialize library */
    if(error)
    {
        printf("FT_Init_FreeType failed\n");
        return -1;
    }
     error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
     if(error)
    {
        printf("FT_New_Face failed\n");
        return -1;
    }
    FT_Set_Pixel_Sizes(face, 24, 0);

/*wstr1*/    
    num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr1, glyphs);
    compute_string_bbox(glyphs, num_glyphs, &bbox);
    /*¼ÆËã³öÒ»ÐÐ×ÖÌåµÄ¿í¶ÈºÍ¸ß¶È*/
     line_box_width = bbox.xMax - bbox.xMin;
     line_box_height = bbox.yMax - bbox.yMin;
     /*ÖØж¨Î»µÚ¶þÐеÄ×ø±ê*/

/*定位使宽字符居中显示*/
     pen.x = (fb_var.xres - line_box_width)/2 * 64;
     pen.y = (fb_var.yres - line_box_height)/2 * 64;
     /*ÏÔʾ*/
     Draw_Glyphs(glyphs, num_glyphs, pen);
    
/*wstr2*/
     num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr2, glyphs);
    compute_string_bbox(glyphs, num_glyphs, &bbox);
    
     line_box_width = bbox.xMax - bbox.xMin;
     line_box_height = bbox.yMax - bbox.yMin;


  /*重新的定位第二宽字符的位置*/  


     pen.x = (fb_var.xres - line_box_width)/2 * 64;
     pen.y = pen.y - 24 *64;
    
     Draw_Glyphs(glyphs, num_glyphs, pen);
    
     FT_Done_Face    ( face );
      FT_Done_FreeType( library );
    

  return 0;
}

测试结果如下: