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

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

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:


大体使用步骤:


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!
相关文章
|
6月前
|
XML 缓存 Linux
在Linux环境下解决Visual Studio Code字体显示异常和字体替换方法。
解决Linux下VS Code字体显示异常,需要对Linux字体渲染机制有所理解,并对VS Code的配置选项进行合理设置。替换字体时则要通过系统字体配置或VS Code设置来完成。通过上述方法,可以有效地解决字体显示问题,从而提升代码编辑的视觉体验。
966 0
|
12月前
|
Ubuntu Linux 编译器
linux下交叉编译licensecc
通过本文的步骤,您可以在Linux环境下成功交叉编译LicenseCC。本文详细介绍了环境准备、工具链安装、源代码下载、CMake配置、编译和验证的全过程。希望这些内容对您的学习和工作有所帮助。
408 62
|
Linux
Linux下使用ls查看文件颜色全部为白色的解决方法,以及Linux中文件颜色介绍
Linux下使用ls查看文件颜色全部为白色的解决方法,以及Linux中文件颜色介绍
848 3
|
Ubuntu Linux 编译器
linux下交叉编译licensecc
通过本文的步骤,您可以在Linux环境下成功交叉编译LicenseCC。本文详细介绍了环境准备、工具链安装、源代码下载、CMake配置、编译和验证的全过程。希望这些内容对您的学习和工作有所帮助。
256 5
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
710 15
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
608 13
|
Linux
linux如何去掉目录背景颜色
linux如何去掉目录背景颜色
627 2
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
1014 3
|
Java Linux 网络安全
【Azure 应用服务】App Service for Linux环境中,如何解决字体文件缺失的情况
【Azure 应用服务】App Service for Linux环境中,如何解决字体文件缺失的情况
241 0
|
传感器 人工智能 网络协议
:嵌入式 Linux 及其用途
【8月更文挑战第24天】
780 0