The FreeType library is a completely free (open source), high-quality and portable font engine. It provides a unified interface to access a variety of font format files, including TrueType , OpenType , Type1, CID, CFF , Windows FON/FNT, X11 PCF etc. It supports the rendering of monochrome bitmaps and anti-aliasing bitmaps. The FreeType library is a highly modular library. Although it is developed using ANSI C, it adopts an object-oriented idea. Therefore, FreeType users can flexibly tailor it. For more information about freetype, please refer to the official website of freetype: https://www.freetype.org/ for more related information.
In the past, when using the Chinese font library in the single-chip microcomputer, it was inevitable to make fonts of various font sizes. And the effect of some production is not very good, and the font size needed needs to be prepared in advance. If you can use FreeType, these are not problems, and various changes can be made. However, freetype may occupy a large amount of resources, even if it has been cut, it may be more than 90k. It is not recommended in the resource-constrained MCU environment. It is better to take the font directly and play it on the resource-rich embedded linux board. .
Freetype source download address:
Cross compilation steps:
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
The entire compilation process was smooth and no errors were reported.
Next, test the simple use on embedded linux, and the image display uses fb0 on linux:
General steps:
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;
}
The following is a simple complete test case and 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;
}
How to change the background of the font, clear an area and fill in the background color, or the background color as shown in the figure below.
How to change the color of the font, the key is here:
If the image displayed on your screen is mirrored and flipped, how to adjust it to display correctly, as follows, just adjust the x and y coordinates.
Attach a complete 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!