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源码下载地址:
交叉编译步骤:
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:
大体使用步骤:
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。
#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 %dbpp\r\n",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/fb0\r\n"); return -1; } if(ioctl(fd_fb,FBIOGET_VSCREENINFO,&var)) { printf("can't get var\r\n"); return -1; } if(ioctl(fd_fb,FBIOGET_FSCREENINFO,&fix)) { printf("can't get fix\r\n"); 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 mmap\r\n"); return -1; } pixel_width = var.bits_per_pixel / 8; line_width = var.xres * pixel_width; memset(fbmem,0xffffff,screen_size); printf("init fb0 ok\n"); printf("fb_var_info:%dx%d, %dbpp\n", 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>\r\n",argc[0]); return -1; } err = init_fb0(); if(err != 0){ printf("init fb0 error\n"); 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 err\r\n"); 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文件:
######################################## #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!