一 : 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>
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;
}