freetype的交叉编译及在嵌入式linux上的简单使用及改变字体背景和颜色

2020-12-16 17:39:18 浏览数 (1)

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

以往单片机中使用中文字库时,免不了需要制作各种字体大小的字模。且有的制作的效果不是很好,需要多大的字体需要提前备好。如果能用上FreeType,这些都不是问题了,且还能各种的变换。但是freetype占的资源可能比较大,即便裁剪过也可能90多k吧,在资源受限的单片机环境中不推荐,还不如直接取字模来得快,在资源丰富的嵌入式linux板上可以玩一下。

freetype源码下载地址:

freetype官网

freetype2.8.1下载

交叉编译步骤:

tar zxvf freetype-2.8.1.tar.gz

cd freetype-2.8.1/

./configure CC=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc --host=arm-linux --prefix=$PWD/INSTALL --with-zlib=no --with-png=n

make

make install

整个编译过程还是很顺利的,没有报错。

接下来测试下在嵌入式linux上的简单使用,图像显示使用linux上的fb0:

大体使用步骤:

代码语言:javascript复制
int main()
{
	FT_Library	library;
	FT_Face		face;
	FT_Error	error;
	FT_UInt		charIdx;
	wchar_t		wch = 'a';
	char*		buffer;		// 用户申请的显示区域空间
	int			startX, startY;	// 字符图像开始装入的位置
 
	// 1. 初始化freetype2库
	error = FT_Init_FreeType(&library);
 
	// 2. 创建一个face
	error = FT_New_Face(library, "C:\windows\font\SURSONG.TTF", 0, &face);
 
	// 3. 设置字体尺寸
	error = FT_Set_Char_Size(face, 16*64, 16*64, 96, 96);
 
	// 4. 获取字符图像索引
	charIdx = FT_Get_Char_Index(face, wch);
 
	// 5. 加载字符图像
	FT_Load_Glyph(face, charIdx, FT_LOAD_DEFAULT);
	if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
	{
		FT_Outline_Embolden(&(face->glyph->outline), 16);	// 加粗轮廓线
	}
 
	// 6. 获取字符位图
	if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
	{
		FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
	}
 
	// 7. 拷贝字符位图到用户的buffer中(用户私人函数)
	// 注意左边的计算方法
	ft2CopyBitmapToBuf(buffer, startX face->glyph->bitmap_left,
		startY face->size->metrics.ascender/64-face->glyph->bitmap_top,
		face->glyph->bitmap);
	startX  = face->glyph->advance.x/64;
}

以下为一个简单的完整测试用例及makefile。

代码语言:javascript复制
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <signal.h>
#include <sys/resource.h>

#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <linux/fb.h>

#include <stdio.h>
#include <wchar.h>
#include <math.h>
#include <ft2build.h>
#include FT_FREETYPE_H
//#include FT_GLYPH_H

int fd_fb;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;

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 r,g,b;
	
	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:
		{
			r = (color>>16) & 0x1f;
			g = (color>>8) & 0x3f;
			b = (color>>0) & 0x1f;
			color = (r<<11) | (g<<5) | (b);
			*pen_16 = color;		
			break;
		}
		case 32:
		{
			*pen_32 = color;
			break;
		}
		default:
		{
			printf("can't support �pprn",var.bits_per_pixel);
			break;
		}
	}
}


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 >= 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 init_fb0(void){
	fd_fb = open("/dev/fb0",O_RDWR);
	if(fd_fb < 0)
	{
		printf("can't open /dev/fb0rn");
		return -1;
	}
	
	if(ioctl(fd_fb,FBIOGET_VSCREENINFO,&var))	
	{
		printf("can't get varrn");
		return -1;
	}	
	if(ioctl(fd_fb,FBIOGET_FSCREENINFO,&fix))
	{
		printf("can't get fixrn");
		return -1;	
	}	
	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 mmaprn");
		return -1;
	}
	pixel_width = var.bits_per_pixel / 8;
	line_width = var.xres * pixel_width;

	memset(fbmem,0xffffff,screen_size);
	printf("init fb0 okn");
	printf("fb_var_info:%dx%d, �ppn", var.xres, var.yres, var.bits_per_pixel);
	return 0;
}

int main(int argv, char **argc)
{
	FT_Library	  library;
	FT_Face 	  face;
	FT_Vector	  pen;	
	wchar_t 	 *new_str = L"我爱你中国1234567890";
	FT_GlyphSlot  slot;
	double        angle;  
	FT_Matrix     matrix;
	int err;
	int n;
	
	if(argv != 2)
	{
		printf("Usage : %s <font_file>rn",argc[0]);
		return -1;
	}
	
	err = init_fb0();
	if(err != 0){
		printf("init fb0 errorn"); 
		return -1;
	}

	err = FT_Init_FreeType(&library);			   	
	err = FT_New_Face(library, argc[1], 0, &face );	
	FT_Set_Pixel_Sizes(face,32,0);

	slot = face->glyph;


	pen.x = var.xres / 2;
	pen.x *= 64;
	pen.y = var.yres / 2;
	pen.y *= 64;
	
	angle = ( 0.0 / 360 ) * 3.14159 * 2;	 

	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 );

	for(n = 0;n < wcslen(new_str);n  )
	{
	    FT_Set_Transform(face,&matrix, &pen);
	    err = FT_Load_Char(face, new_str[n],FT_LOAD_RENDER);
		if(err)
		{
			printf("FT load char errrn");
			return -1;
		}		
		draw_bitmap(&slot->bitmap,slot->bitmap_left,var.yres - slot->bitmap_top);
		pen.x  = 64*32;
		//pen.y  = 64*32;
	}	

	return 0;
}

如何改变字体的背景呢,clear一个区域,填充下背景色即可,或者如下图所示背景色的地方。

如何改变字体的颜色呢,关键在这里:

如果你的屏幕显示的图像是镜像翻转的,如何调整让显示正确呢,如下,调整下x,y坐标即可。

附完整的makefile文件:

代码语言:javascript复制
########################################
#makefile
########################################
#****************************************************************************
# Cross complie path
#****************************************************************************
# CHAIN_ROOT=/home/yang/imax283/ctools/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/bin

# CROSS_COMPILE=$(CHAIN_ROOT)/arm-none-linux-gnueabi-

CHAIN_ROOT= /home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin
CROSS_COMPILE=$(CHAIN_ROOT)/arm-linux-gnueabihf-

#CROSS_COMPILE = 

CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g  
AS     := $(CROSS_COMPILE)as
AR     := $(CROSS_COMPILE)ar 
LD     := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib
OBJDUMP:= $(CROSS_COMPILE)objdump
OBJCOPY:= $(CROSS_COMPILE)objcopy
STRIP  := $(CROSS_COMPILE)strip

#±àÒëÖ¸¶¨×ÓĿ¼
SUBDIRS := 

define make_subdir
 @ for subdir in $(SUBDIRS) ; do 
 ( cd $$subdir && make $1) 
 done;
endef

#output
BINARY  := test
OBJ_DIR := 

#CFLAGS=   -I./GUI_X -I./GUI/Core -I./GUI/WM -I./GUI/Widget
CFLAGS=  -I./freetype/include/freetype2


LDSCRIPT=  -lfreetype -lm
LDFLAGS= -L./freetype/lib 

# SRC_C=$(shell find . -name "*.c")
# OBJ_C=$(patsubst %.c, %.o, $(SRC_C))
# SRCS := $(SRC_C) $(SRC_C)
# OBJS := $(OBJ_C) 

SRC  = $(wildcard *.c)
DIR  = $(notdir $(SRC))
OBJS = $(patsubst %.c,$(OBJ_DIR)%.o,$(DIR))
#OBJS=  testdb.o
#CFLAGS=-std=c99
#@echo Building lib...
#$(call make_subdir)
.PHONY: clean lib
all:  prebuild  $(BINARY)

prebuild:
	@echo Building app...

$(BINARY) : $(OBJS)
	@echo Generating ...
	$(CC) -o $(BINARY) $(OBJS) $(LDFLAGS) $(LDSCRIPT) 
	@echo OK!

$(OBJ_DIR)%.o : %.c
	$(CC) -c $(CFLAGS) $< -o  $@
	
lib:
	@echo Building lib...
	$(call make_subdir)
	
clean:
	rm -f $(OBJ_DIR)*.o
	find . -name "*.[od]" |xargs rm
	@echo Removed!

0 人点赞