Programmation d'application dans un environnement Linux (6): Framebuffer

一 : API Framebuffer

1 、int open (const char * chemin, int flags)

Exemple:

int fd_fb;

fd_fb = ouvert ("/ dev / fb0", O_RDWR);

2 、int ioctl (int fd, requête longue non signée, ...)

Exemple:

struct fb_var_screeninfo var;

ioctl (fd_fb, FBIOGET_VSCREENINFO et var)

Selon la commande request , le pilote de périphérique renvoie les données de sortie

Pour FBIOGET_VSCREENINFO, l' instruction de retour var est la structure fb_var_screeninfo :

Il contient des informations sur l'écran LCD: xres (pixels totaux dans la direction x), yres (pixels totaux dans la direction y), bits_par_pixel (nombre de bits occupés par chaque pixel)

Selon les informations obtenues, certaines variables peuvent être calculées:

Octets occupés par des pixels dans chaque ligne: line_width = var.xres * var.bits_per_pixel / 8;

Octets occupés par chaque pixel: pixel_width = var.bits_per_pixel / 8;

Octets occupés par tous les pixels: screen_size = var.xres * var.yres * var.bits_per_pixel / 8;

3 、void * mmap (void * addr, size_t length, int prot, int flags, int fd, off_t offset)

Exemple:

unsigned char * fbmem;

fbmem = (caractère non signé *) mmap (NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);

addr: indique l'adresse de départ de la mémoire mappée, généralement NULL signifie laisser le système choisir par lui-même et renvoyer l'adresse après le succès

length: indique la taille du contenu à mapper

prot: indique le mode de protection de la zone cartographiée

①La zone de mappage PROT_EXEC peut être exécutée

La zone de mappage PROT_READ peut être lue et écrite

③La zone de mappage PROT_WRITE peut être écrite

④ La zone de mappage PROT_NONE n'est pas accessible

Représente les différentes caractéristiques de la zone cartographique:

①MAP_SHARED signifie que les données écrites dans la zone de mappage seront recopiées dans le fichier, et le fichier d'origine sera modifié.

②MAP_PRIVATE signifie que l'opération de la zone de mappage produira une copie du fichier de mappage, et toute modification de cette zone ne sera pas réécrite dans le contenu du fichier d'origine.

Deux: construction de l'environnement FreeType

1. Téléchargez et décompressez le package d'installation

tar xjf freetype-2.4.10.tar.bz2

2. Configuration

--host: outil de compilation

--prefix: configure le répertoire cible

jun @ zero: ~ / work / file / application / 01_framebuffer / freetype-2.4.10 $ ./configure --host = arm-linux-gnueabihf --prefix = / home / jun / work / tool / arm-linux-gcc /gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr

3. Compilez et installez

Vous devez créer un fichier avant de compiler et d'installer: interne

jun @ zero: ~ / work / tool / arm-linux-gcc / gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf / arm-linux-gnueabihf / libc / usr / include / freetype2 / freetype $ mkdir internal -p

Responsable des erreurs:

'/home/jun/work/tool/arm-linux-gcc/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/freetype2/freetype/internal' Échec: aucun fichier ou répertoire de ce type

Compiler et installer: faire installer

4. Déplacez la bibliothèque freetype pour éviter d'avoir à spécifier le chemin lors de la compilation des fichiers ultérieurement

 mv /home/jun/work/tool/arm-linux-gcc/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/freetype2/freetype / home / jun / work / tool / arm-linux-gcc / gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf / arm-linux-gnueabihf / libc / usr / include /

Trois: Introduction à FreeType

1. Fichier d'en-tête

#include <ft2build.h>

#include FT_FREETYPE_H

Depuis FreeType 2.1.6, l'ancien schéma d'inclusion de fichier d'en-tête n'est plus pris en charge. Cela signifie que si vous procédez comme suit, vous obtiendrez maintenant une erreur:

#include <freetype / freetype.h>

#include <freetype / ftglyph.h>
 

2. Initialisez la bibliothèque

Créez une bibliothèque de variables de type FT_Librart, puis passez la fonction FT_Init_FreeType et renvoyez 0 avec succès

#include <ft2build.h>
#include FT_FREETYPE_H

FT_Library  library;

...

error = FT_Init_FreeType( &library );
if ( error )
{
    ... an error occurred during library initialization ...
}

3. Charger les polices

Ouvrez un fichier de police ".ttf" en appelant FT_New_Face et obtenez une face d'objet de type FT_Face pour décrire la police.

FT_Face     face;      /* handle to face object */

error = FT_New_Face( library,
                       "/usr/share/fonts/truetype/arial.ttf",
                       0,
                       &face );
if ( error == FT_Err_Unknown_File_Format )
{
    ... the font file could be opened and read, but it appears
    ... that its font format is unsupported
}
else if ( error )
{
    ... another error code means that the font file could not
    ... be opened or read, or simply that it is broken...
}

Si le fichier de police a été chargé dans la mémoire, vous pouvez utiliser FT_New_Memory_Face () pour obtenir la face de l'objet au lieu du chemin du fichier de police. Notez que vous ne pouvez pas appeler FT_Done_Face () avant de libérer la mémoire.

error = FT_New_Memory_Face( library,
                              buffer,    /* first byte in memory */
                              size,      /* size in bytes        */
                              0,         /* face_index           */
                              &face );

4. Visiter le visage

Vous pouvez accéder directement aux données de visage par référence

FT_GlyphSlot  slot;
slot = face->glyph;

5. Définissez la taille des pixels

a. Pour un périphérique 300 x 300 dpi, la taille des caractères est définie sur 16 pt

  error = FT_Set_Char_Size(
            face,    /* handle to face object           */
            0,       /* char_width in 1/64th of points  */
            16*64,   /* char_height in 1/64th of points */
            300,     /* horizontal device resolution    */
            300 );   /* vertical device resolution      */

b. Spécifiez la taille de pixel par vous-même, la valeur d'une dimension est 0 signifie la même chose que l'autre dimension

  error = FT_Set_Pixel_Sizes(
            face,   /* handle to face object */
            0,      /* pixel_width           */
            16 );   /* pixel_height          */

6. Conversion de glyphes

Lors du chargement d'une image de glyphe, vous pouvez effectuer une transformation spécifiée, qui n'est applicable qu'au format de police vectorielle

FT_Vector     pen;
FT_Matrix	  matrix;				  /* transformation matrix */

error = FT_Set_Transform(
            face,       /* target face object    */
            &matrix,    /* pointer to 2x2 matrix */
            &pen);   /* pointer to 2d vector  */

7, chargement de la police

wchar_t *chinese_str = L"繁";
error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );

Quatre: Exemple complet

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

#define FONTDATAMAX 4096

static const unsigned char fontdata_8x16[FONTDATAMAX] = {
... ...
	/* 1 0x01 '^A' */
	0x00, /* 00000000 */
	0x00, /* 00000000 */
	0x7e, /* 01111110 */
	0x81, /* 10000001 */
	0xa5, /* 10100101 */
	0x81, /* 10000001 */
	0x81, /* 10000001 */
	0xbd, /* 10111101 */
	0x99, /* 10011001 */
	0x81, /* 10000001 */
	0x81, /* 10000001 */
	0x7e, /* 01111110 */
	0x00, /* 00000000 */
	0x00, /* 00000000 */
	0x00, /* 00000000 */
	0x00, /* 00000000 */
... ...
}
int fd_fb;
struct fb_var_screeninfo var;	/* Current var */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;

int fd_hzk16;
struct stat hzk_stat;
unsigned char *hzkmem;


/**********************************************************************
 * 函数名称: lcd_put_pixel
 * 功能描述: 在LCD指定位置上输出指定颜色(描点)
 * 输入参数: x坐标,y坐标,颜色
 * 输出参数: 无
 ***********************************************************************/ 
void lcd_put_pixel(int x, int y, unsigned int color)
{
	unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;
	unsigned short *pen_16;	
	unsigned int *pen_32;	

	unsigned int red, green, blue;	

	pen_16 = (unsigned short *)pen_8;
	pen_32 = (unsigned int *)pen_8;

	switch (var.bits_per_pixel)
	{
		case 8:
		{
			*pen_8 = color;
			break;
		}
		case 16:
		{
			/* 565 */
			red   = (color >> 16) & 0xff;
			green = (color >> 8) & 0xff;
			blue  = (color >> 0) & 0xff;
			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*pen_16 = color;
			break;
		}
		case 32:
		{
			*pen_32 = color;
			break;
		}
		default:
		{
			printf("can't surport %dbpp\n", var.bits_per_pixel);
			break;
		}
	}
}
/**********************************************************************
 * 函数名称: lcd_put_ascii
 * 功能描述: 在LCD指定位置上显示一个8*16的字符
 * 输入参数: x坐标,y坐标,ascii码
 ***********************************************************************/ 
void lcd_put_ascii(int x, int y, unsigned char c)
{
	unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
	int i, b;
	unsigned char byte;

	for (i = 0; i < 16; i++)
	{
		byte = dots[i];
		for (b = 7; b >= 0; b--)
		{
			if (byte & (1<<b))
			{
				/* show */
				lcd_put_pixel(x+7-b, y+i, 0xffffff); /* 白 */
			}
			else
			{
				/* hide */
				lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
			}
		}
	}
}
/**********************************************************************
 * 函数名称: lcd_put_chinese
 * 功能描述: 在LCD指定位置上显示一个16*16的汉字
 * 输入参数: x坐标,y坐标,ascii码
 ***********************************************************************/ 
void lcd_put_chinese(int x, int y, unsigned char *str)
{
	unsigned int area  = str[0] - 0xA1;
	unsigned int where = str[1] - 0xA1;
	unsigned char *dots = hzkmem + (area * 94 + where)*32;
	unsigned char byte;

	int i, j, b;
	for (i = 0; i < 16; i++)
		for (j = 0; j < 2; j++)
		{
			byte = dots[i*2 + j];
			for (b = 7; b >=0; b--)
			{
				if (byte & (1<<b))
				{
					/* show */
					lcd_put_pixel(x+j*8+7-b, y+i, 0xffffff); /* 白 */
				}
				else
				{
					/* hide */
					lcd_put_pixel(x+j*8+7-b, y+i, 0); /* 黑 */
				}
				
			}
		}
	
}

/**********************************************************************
 * 函数名称: draw_bitmap
 * 功能描述: 根据bitmap位图,在LCD指定位置显示汉字
 * 输入参数: x坐标,y坐标,位图指针
 ***********************************************************************/ 
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;

	//printf("x = %d, y = %d\n", x, y);

  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 >= var.xres || j >= var.yres )
        continue;

      //image[j][i] |= bitmap->buffer[q * bitmap->width + p];
      lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);
    }
  }
}

int main(int argc, char **argv)
{
	unsigned char str[] = "中";
	wchar_t *chinese_str = L"繁";

	FT_Library	  library;
	FT_Face 	  face;
	int error;
    FT_Vector     pen;
	FT_GlyphSlot  slot;
	FT_Matrix	  matrix;				  /* transformation matrix */
	double        angle;

	if (argc != 3)
	{
		printf("Usage : %s <font_file> <angle>\n", argv[0]);
		return -1;
	}
		

	fd_fb = open("/dev/fb0", O_RDWR);
	if (fd_fb < 0)
	{
		printf("can't open /dev/fb0\n");
		return -1;
	}

	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
	{
		printf("can't get var\n");
		return -1;
	}

	line_width  = var.xres * var.bits_per_pixel / 8;
	pixel_width = var.bits_per_pixel / 8;
	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
	fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
	if (fbmem == (unsigned char *)-1)
	{
		printf("can't mmap\n");
		return -1;
	}

	fd_hzk16 = open("HZK16", O_RDONLY);
	if (fd_hzk16 < 0)
	{
		printf("can't open HZK16\n");
		return -1;
	}
	if(fstat(fd_hzk16, &hzk_stat))
	{
		printf("can't get fstat\n");
		return -1;
	}
	hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
	if (hzkmem == (unsigned char *)-1)
	{
		printf("can't mmap for hzk16\n");
		return -1;
	}

	/* 清屏: 全部设为黑色 */
	memset(fbmem, 0, screen_size);

	lcd_put_ascii(var.xres/2, var.yres/2, 'A');

	printf("chinese code: %02x %02x\n", str[0], str[1]);
	lcd_put_chinese(var.xres/2 + 8,  var.yres/2, str);

	/* 显示矢量字体 */
	error = FT_Init_FreeType( &library );			   /* initialize library */
	/* error handling omitted */
	
	error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
	/* error handling omitted */	
	slot = face->glyph;

	FT_Set_Pixel_Sizes(face, 24, 0);

	/* 确定座标:
	 * lcd_x = var.xres/2 + 8 + 16
	 * lcd_y = var.yres/2 + 16
	 * 笛卡尔座标系:
	 * x = lcd_x = var.xres/2 + 8 + 16
	 * y = var.yres - lcd_y = var.yres/2 - 16
	 */
	pen.x = (var.xres/2 + 8 + 16) * 64;
	pen.y = (var.yres/2 - 16) * 64;

	angle = ( 1.0 * strtoul(argv[2], NULL, 0) / 360 ) * 3.14159 * 2;	  /* use 25 degrees 	*/
	/* set up matrix */
	matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
	matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
	matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
	matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

    /* set transformation */
    FT_Set_Transform( face, &matrix, &pen);

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );
	if (error)
	{
		printf("FT_Load_Char error\n");
		return -1;
	}
	
    draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 var.yres - slot->bitmap_top);

	return 0;	
}

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_34968572/article/details/107229363
conseillé
Classement