Linux下矢量字体运用 ​

一、freetype简介

FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,可以非常方便我们开发字体显示相关的程序功能。它支持单色位图、反走样位图的渲染。FreeType库是高度模块化的程序库,虽然它是使用ANSI C开发,但是采用面向对象的思想,因此,FreeType的用户可以灵活地对它进行裁剪。关于freetype的详细信息可以参考freetype的官方网站:https://www.freetype.org/来获取更多相关的信息。

CSDN下载地址:https://download.csdn.net/download/tech_pro/9873843

Linux下矢量字体运用 ​

二、下载源码编译安装

2.1 编译freetype

[root@wbyq pc_work]# tar xvf /mnt/hgfs/linux-share-dir/freetype-2.4.10.tar.bz2

[root@wbyq freetype-2.4.10]# ./configure --host=arm-linux --prefix=$PWD/_install

[root@wbyq freetype-2.4.10]# make && make install

[root@wbyq freetype-2.4.10]# tree _install/

_install/

├── bin

│ └── freetype-config

├── include

│ ├── freetype2

│ │ └── freetype

│ │ ├── config

│ │ │ ├── ftconfig.h

│ │ │ ├── ftheader.h

│ │ │ ├── ftmodule.h

│ │ │ ├── ftoption.h

│ │ │ └── ftstdlib.h

│ │ ├── freetype.h

│ │ ├── ftadvanc.h

│ │ ├── ftbbox.h

│ │ ├── ftbdf.h

│ │ ├── ftbitmap.h

│ │ ├── ftbzip2.h

│ │ ├── ftcache.h

│ │ ├── ftchapters.h

│ │ ├── ftcid.h

│ │ ├── fterrdef.h

│ │ ├── fterrors.h

│ │ ├── ftgasp.h

│ │ ├── ftglyph.h

│ │ ├── ftgxval.h

│ │ ├── ftgzip.h

│ │ ├── ftimage.h

│ │ ├── ftincrem.h

│ │ ├── ftlcdfil.h

│ │ ├── ftlist.h

│ │ ├── ftlzw.h

│ │ ├── ftmac.h

│ │ ├── ftmm.h

│ │ ├── ftmodapi.h

│ │ ├── ftmoderr.h

│ │ ├── ftotval.h

│ │ ├── ftoutln.h

│ │ ├── ftpfr.h

│ │ ├── ftrender.h

│ │ ├── ftsizes.h

│ │ ├── ftsnames.h

│ │ ├── ftstroke.h

│ │ ├── ftsynth.h

│ │ ├── ftsystem.h

│ │ ├── fttrigon.h

│ │ ├── fttypes.h

│ │ ├── ftwinfnt.h

│ │ ├── ftxf86.h

│ │ ├── t1tables.h

│ │ ├── ttnameid.h

│ │ ├── tttables.h

│ │ ├── tttags.h

│ │ └── ttunpat.h

│ └── ft2build.h

├── lib

│ ├── libfreetype.a

│ ├── libfreetype.la

│ ├── libfreetype.so -> libfreetype.so.6.9.0

│ ├── libfreetype.so.6 -> libfreetype.so.6.9.0

│ ├── libfreetype.so.6.9.0

│ └── pkgconfig

│ └── freetype2.pc

└── share

aclocal

freetype2.m4

9 directories, 56 files

[root@wbyq freetype-2.4.10]#

2.2 部署编译环境和运行环境

1. 拷贝生成的库到开发板

[root@wbyq freetype-2.4.10]# cp _install/lib/*.so* /home/wbyq/rootfs/lib/ -fdv

2. 再将_install目录下的头文件和库文件拷贝到编译器的目录下,方便编译器在编译程序时能找到库和头文件。

[wbyq@wbyq freetype-2.4.10]$ sudo cp _install/include/ft2build.h /home/wbyq/work/arm-linux-gcc/opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/sys-root/usr/include/

[wbyq@wbyq freetype-2.4.10]$ sudo cp _install/include/freetype2/freetype/ /home/wbyq/work/arm-linux-gcc/opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/sys-root/usr/include/ -rf

[wbyq@wbyq freetype-2.4.10]$ sudo cp _install/lib/*.so* /home/wbyq/work/arm-linux-gcc/opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/sys-root/usr/lib/ -dv

3. 在编译调用freetype库函数的源程序时,需要指定库文件。

比如:[wbyq@wbyq lcd_freetype]$ arm-linux-gcc freetype.c -lfreetype

2.3 windows电脑上的矢量字体存放目录

Linux下矢量字体运用 ​

2.4 示例代码

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <termios.h>

#include <unistd.h>

#include <string.h>

#include <linux/fb.h>

#include <sys/mman.h>

#include <math.h>

#include <wchar.h>

#include <ft2build.h>

#include FT_FREETYPE_H

#include FT_STROKER_H

#define LCD_DEVICE "/dev/fb0"

int lcd_fd;

struct fb_var_screeninfo vinfo;//可变参数

struct fb_fix_screeninfo finfo; //固定参数

unsigned char *lcd_mem=NULL; //LCD首地址

typedef unsigned int u32;

typedef unsigned short u16;

typedef unsigned char u8;

/*定义一个结构体存放矢量字体的配置*/

struct FREE_TYPE_CONFIG

{

FT_Library library;

FT_Face face;

FT_GlyphSlot slot;

FT_Vector pen; /* untransformed origin */

FT_Error error;

FT_BBox bbox;

FT_Glyph glyph;

};

struct FREE_TYPE_CONFIG FreeTypeConfig;

/*

函数功能: 封装画点函数

函数参数: u32 x,u32 y,u16 c

*/

void LCD_DrawPoint(u32 x,u32 y,u32 c)

{

u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);

*lcd_p=c;

}

/*

函数功能: 封装读点函数

函数参数: u32 x,u32 y,u16 c

*/

u32 LCD_ReadPoint(u32 x,u32 y)

{

u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);

return *lcd_p;

}

/*LCD显示矢量字体的位图信息

*bitmap : 要显示的字体的矢量位图

*x : 显示的x坐标

*y : 显示的y坐标

*/

void LCD_DrawBitmap(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>x_max)||(j>y_max)||(i<0)||(j<0))continue;

if(bitmap->buffer[q*bitmap->width+p]!=0)

{

LCD_DrawPoint(i, j,0xFF0033);

}

else

{

LCD_DrawPoint(i, j,0xFFFFFF);

}

}

}

}

/*

函数功能: 初始化FreeType配置

*/

int InitConfig_FreeType(char *font_file)

{

FT_Error error;

/*1. 初始化freetype库*/

error=FT_Init_FreeType(&FreeTypeConfig.library);

if(error)

{

printf("freetype字体库初始化失败.n");

return -1;

}

/*2. 打开加载的字体文件*/

error=FT_New_Face(FreeTypeConfig.library,font_file,0,&FreeTypeConfig.face);

if(error)

{

printf("矢量字体文件加载失败.n");

return -2;

}

return 0;

}

/*

函数功能: 释放FreeType配置

*/

void FreeType_Config(void)

{

FT_Done_Face(FreeTypeConfig.face);

FT_Done_FreeType(FreeTypeConfig.library);

}

/*

函数功能: 在LCD屏显示一串文本数据

函数参数:

u32 x 坐标位置

u32 y 坐标位置

u32 size 字体大小

wchar_t *text 显示的文本数据

*/

int LCD_DrawText(u32 x,u32 y,u32 size,wchar_t *text)

{

FT_Error error;

int i = 0;

int bbox_height_min = 10000;

int bbox_height_max = 0;

/*3. 设置字符的像素的大小为size*size*/

error=FT_Set_Pixel_Sizes(FreeTypeConfig.face,size,0);

if(error)

{

printf("字符的像素大小设置失败.n");

return -1;

}

/*4. 设置字体文件的轮廓的插槽*/

FreeTypeConfig.slot=FreeTypeConfig.face->glyph;

/* 设置坐标为原点坐标

将LCD坐标转换成笛卡尔坐标

单位是 1/64 Point

*/

FreeTypeConfig.pen.x=x*64;

FreeTypeConfig.pen.y=(vinfo.yres-size-y)*64;

/*5. 循环的将文字显示出来*/

for(i=0;i<wcslen(text);i++)

{

FT_Set_Transform(FreeTypeConfig.face,0,&FreeTypeConfig.pen);//设置字体的起始坐标位置

/*装载字符编码,填充face的glyph slot成员*/

error=FT_Load_Char(FreeTypeConfig.face,text[i],FT_LOAD_RENDER);

if(error)

{

printf("装载字符编码失败.n");

return -1;

}

/*通过glyph slot来获得glyph*/

FT_Get_Glyph(FreeTypeConfig.slot,&FreeTypeConfig.glyph);

/*通过glyph来获得cbox*/

FT_Glyph_Get_CBox(FreeTypeConfig.glyph,FT_GLYPH_BBOX_TRUNCATE,&FreeTypeConfig.bbox);

/*获得字体高度的最大值和最小值*/

if(bbox_height_min>FreeTypeConfig.bbox.yMin)bbox_height_min=FreeTypeConfig.bbox.yMin;

if(bbox_height_max<FreeTypeConfig.bbox.yMax)bbox_height_max=FreeTypeConfig.bbox.yMax;

/*画点,把笛卡尔坐标转换成LCD坐标*/

LCD_DrawBitmap(&FreeTypeConfig.slot->bitmap,

FreeTypeConfig.slot->bitmap_left,

vinfo.yres-FreeTypeConfig.slot->bitmap_top);

if(FreeTypeConfig.slot->bitmap_left+size*2>vinfo.xres)

{

FreeTypeConfig.pen.x=0; //更新X坐标位置

FreeTypeConfig.pen.y=(vinfo.yres-size-y-size)*64; //更新Y坐标位置

}

else

{

/* 更新原点坐标位置 */

FreeTypeConfig.pen.x+=FreeTypeConfig.slot->advance.x;

FreeTypeConfig.pen.y+=FreeTypeConfig.slot->advance.y;

}

}

return 0;

}

int main(int argc,char **argv)

{

if(argc!=2)

{

printf("./app <xxx.ttf 字体文件>n");

return 0;

}

/*1. 打开设备文件*/

lcd_fd=open(LCD_DEVICE,O_RDWR);

if(lcd_fd<0)

{

printf("%s open error.n",LCD_DEVICE);

return 0;

}

/*2. 获取可变参数*/

ioctl(lcd_fd,FBIOGET_VSCREENINFO,&vinfo);

printf("x=%d,y=%d,pixel=%dn",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);

/*3. 获取固定参数*/

ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo);

printf("smem_len=%dn",finfo.smem_len);

printf("line_length=%dn",finfo.line_length);

/*4. 映射LCD地址*/

lcd_mem=mmap(NULL,finfo.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);

if(lcd_mem==NULL)

{

printf("映射LCD地址失败.n");

return -1;

}

memset(lcd_mem,0xFFFFFF,finfo.smem_len);

/*5. 初始化配置FreeType*/

InitConfig_FreeType(argv[1]);

/*6. 在指定位置显示文本*/

/*

wcslen() 函数用于计算宽字符的个数,支持区分中文和英文字符,文本需要在UTF-8编码下。

定义宽字符串示例:

wchar_t *wp=L"1234567890中国"; //12

printf("wcslen p:%dn",wcslen(wp)); 返回值是12

*/

LCD_DrawText(50,56*0,56,L"北京万邦易嵌科技有限公司");

LCD_DrawText(150,56*1,56,L"www.wanbangee.com");

LCD_DrawText(200,56*3,48,L"FreeType矢量字体");

LCD_DrawText(150,56*5,80,L"Linux驱动开发");

/*7. 释放FreeType配置*/

FreeType_Config();

close(lcd_fd);

return 0;

}

2.5 编译源代码的Makefile示例

all:

arm-linux-gcc video_app.c -I /home/wbyq/work/freetype-2.4.10/_install/include -I /home/wbyq/work/freetype-2.4.10/_install/include/freetype2 -o app -lfreetype -ljpeg

cp app /home/wbyq/work/rootfs/code

rm app -f

2.6 运行程序效果示例

Linux下矢量字体运用 ​

Linux下矢量字体运用 ​

发表评论

相关文章