Skip to content

LV100-FreeType简介

一、LCD 显示字符的方式?

1. 原始方式——取模

LCD 显示屏是由 width * height 个像素点构成的,显示字符,一个非常容易想到的方法便是对字符取模,然后在 LCD 屏上打点显示字符;以前学习过单片机的话,应该会接触过一些显示屏,如 oled、 或者其它一些点阵式的显示屏, 其实这些显示屏显示字符的原理都是一样的,如下所示:

image-20241014215505516

我们可以通过一些字符取模软件获取到字符的子模; 所谓字模,其实就是一个二维数组, 用于表示字符点阵中,哪些小方块应该要填充颜色、哪些小方块不填充颜色。如上图“正”字符点阵,这是一个宽度为 64(64 个小方块)、高度为 86(86 个小方块)的字符点阵, 我们会使用一个二维数组来表示这个字符点阵:

shell
unsigned char arr[86][8];

也就是一个 86 行 8 列的 unsigned char 类型数组, 数组存储的其实就是字符的位图数据, 字符点阵中的每一个小方块对应一个 bit 位,因为一行一共有 64 个小方块、也就对应 8 个字节(8 * 8 = 64); 将填充颜色的方块使用 1 表示、不填充颜色的方块使用 0 来表示,所以一个小方块刚好可以使用一个 bit 位来描述。

2. 有没有其他方式?

使用取模显示那种方式还是非常简单地,自己取模、自己写函数打点显示,但是取模很麻烦!实际的应用项目一般肯定不会这么干,除非我们的程序就是显示那么几个固定的字符。

操作系统中通常都会有很多的字体文件,如 Windows 系统“C:\Windows\Fonts”目录下就有很多的字体文件,如下所示:

image-20260107170805021

字体文件的格式也有很多种,如 otf、 ttf、 ttc 等,这里就不列举了,可以自己百度一下; Linux 系统中, 字体文件通常会放在 /usr/share/fonts 目录下,

image-20241014220630847

有了字体文件之后,我们就不需要再对字符进行取模了,它们已经编码进了字体文件中,我们只需要解析字体文件、访问字体文件,从字体文件中读取出字符的位图数据即可!

当然,这些复杂的解析过程并不需要我们自己去实现,有很多开源的字体引擎可以帮助我们来处理这些复杂的解析过程,如 freetype 库。

3. 矢量字体

使用点阵字库显示英文字母、汉字时, 大小固定, 如果放大缩小则会模糊甚至有锯齿出现,为了解决这个问题,引用矢量字体。矢量字体形成分三步:

第 1 步 确定关键点(有些解释为字形,都是一个意思啦);第 2 步 使用数学曲线( 贝塞尔曲线) 连接头键点;第 3 步 填充闭合区线内部空间。

什么是关键点?以字母“ A”为例:

imgimgimg
它的的关键点如图中的黄色所示 再用数学曲线(比如贝塞尔曲线)将关键点都连接起来, 得到一系列的封闭的曲线 最后把封闭空间填满颜色,就显示出一个 A 字母

如果需要放大或者缩小字体, 关键点的相对位置是不变的, 只要数学曲线平滑,字体就不会变形。

二、FreeType 简介

1. FteeType 是什么?

FreeType 一个完全免费(开源)的软件字体引擎库,设计小巧、高效、高度可定制且可移植,它提供了统一的接口来访问多种不同格式的字体文件,从而实现矢量字体显示。 。 它提供了一个简单、易于使用且统一的接口来访问字体文件的内容,从而大大简化了这些任务。它有以下优点:

(1)支持多种字体格式文件,并提供了统一的访问接口;

(2)支持单色位图、反走样位图渲染,这使字体显示质量达到 Mac 的水平;

(3)采用面向对象思想设计,用户可以灵活的根据需要裁剪。

但 FreeType 也有缺点,它太大了,即使是裁剪后的阉割版,其代码量也有将近 12 万行,在 Flash 非常小的开发板可能放不下,此时可以考虑用代码量较小的 stb_truetype 库

“FreeType”也称为“FreeType 2”,以区别于旧的、已弃用的“FreeType 1”库, Freetype 1 库已经不再维护和支持了。 FreeType 是一个免费、开源、可移植且高质量的字体引擎,

2. 官网在哪?

官网应该是这个:The FreeType Project

3. 参考文档

FreeType 库支持的功能很多、提供给用户的库函数也很多, 官网肯定也为我们提供了文档啦:

这个链接是一份中文参考文档,可以作为参考:freetype 使用详解(中文) - 道客巴巴 (doc88.com)。我们也可以下载每一个版本的文档:Index of /releases/freetype/ (gnu.org)

image-20260107172321089

像这些带有 doc 的,都是对应版本的官方文档。下载后解压,主要可以看这个目录:

image-20241017231255670

三、FreeType 库移植

1. 下载源码

我们到这里下载:Index of /releases/freetype/ (gnu.org)

image-20260107172444730

正点原子出厂系统中的是 2.6 版本,这里我选了个 2.8 版本,由于是第一次用,防止踩坑,和教程采用差不多的一个版本。下载完毕后解压:

shell
tar xf freetype-2.8.tar.gz
cd freetype-2.8
ls
image-20241014224612686

2. 编译源码

  • 创建安装目录
shell
mkdir -p /home/sumu/9arm-linux-lib/freetype-2.8/freetype_out
  • 配置编译选项

FreeType 库基于模块化设计,意味着我们可以对其进行裁剪,将不需要的功能模块从配置中移除,减小库文件的体积;除此之外,

FreeType 还支持很多配置选项, 如果想要对 FreeType 做一些自定义配置或者对其进行裁剪,可以参考 FreeType 源码目录下 docs/CUSTOMIZE 文档,该文件对此有比较详细的说明,建议看一看,如果有需求的话。 docs 目录下还有其它很多的说明文档, 也都可以看一看。

这里我们简单地配置一下,打开 include/freetype/config/ftoption.h 文件:

c
vim include/freetype/config/ftoption.h

该文件定义了很多的配置宏,我们可以选择使能或禁用这些配置选项,具体配置哪些功能,根据自己的需求来就是了,每一个配置宏都有详细地解释说明。 这里我们打开以下两个配置宏:

c
#define FT_CONFIG_OPTION_SYSTEM_ZLIB
#define FT_CONFIG_OPTION_USE_PNG

我们找到这两个宏,默认情况下,这两个都被注释掉了,所以是没有使能的; 把这两个宏的注释去掉,使能这两个配置宏。 但是我后来发现这里其实没必要注释掉,配置完之后会自动打开的,编译选项中是有这两个宏的:

shell
sumu@sumu-virtual-machine:~/9arm-linux-lib/freetype-2.8$ make
./builds/unix/libtool --mode=compile arm-linux-gnueabihf-gcc -pedantic -ansi -I/home/sumu/9arm-linux-lib/freetype-2.8/objs -I./builds/unix -I/home/sumu/9arm-linux-lib/freetype-2.8/include -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -c -Wall -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib -DFT_CONFIG_OPTION_SYSTEM_ZLIB -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib -DFT_CONFIG_OPTION_USE_PNG -DFT_CONFIG_CONFIG_H="<ftconfig.h>" -DFT2_BUILD_LIBRARY -DFT_CONFIG_MODULES_H="<ftmodule.h>"  -o /home/sumu/9arm-linux-lib/freetype-2.8/objs/ftsystem.lo /home/sumu/9arm-linux-lib/freetype-2.8/src/base/ftsystem.c
libtool: compile:  arm-linux-gnueabihf-gcc -pedantic -ansi -I/home/sumu/9arm-linux-lib/freetype-2.8/objs -I./builds/unix -I/home/sumu/9arm-linux-lib/freetype-2.8/include -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -c -Wall -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib -DFT_CONFIG_OPTION_SYSTEM_ZLIB -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib -DFT_CONFIG_OPTION_USE_PNG "-DFT_CONFIG_CONFIG_H=<ftconfig.h>" -DFT2_BUILD_LIBRARY "-DFT_CONFIG_MODULES_H=<ftmodule.h>" /home/sumu/9arm-linux-lib/freetype-2.8/src/base/ftsystem.c  -fPIC -DPIC -o /home/sumu/9arm-linux-lib/freetype-2.8/objs/.libs/ftsystem.o

第一个配置宏表示使用系统安装的 zlib 库,因为 FreeType 支持 Gzip 压缩文件,会使用到 zlib 库, zlib 之前我们移植好了;第二个配置宏表示支持 PNG bitmap 位图,因为 FreeType 可以加载 PNG 格式的彩色位图字形,需要依赖于 libpng 库,这个库前面我们也是移植好了。

配置好之后,保存、退出 ftoption.h 文件,接着执行如下命令对 FreeType 工程源码进行配置按理来说下面的配置应该就可以了:

shell
./configure --prefix=/home/sumu/9arm-linux-lib/freetype-2.8/freetype_out/ --host=arm-linux-gnueabihf --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib" ZLIB_LIBS=-lz LIBPNG_CFLAGS="-I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib" LIBPNG_LIBS=-lpng

但是,这样配置的话,编译器无法生效:

image-20241015074149487

要通过 export 来设置 CC 环境变量才行:

shell
export CC=arm-linux-gnueabihf-gcc
./configure --prefix=/home/sumu/9arm-linux-lib/freetype-2.8/freetype_out/ --host=arm-linux-gnueabihf --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib" ZLIB_LIBS=-lz LIBPNG_CFLAGS="-I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib" LIBPNG_LIBS=-lpng
image-20241015074333063

但是这个时候最后编译会报找不到 zlib 和 png 的库,不是很清楚原因是什么,就暂时先通过 export 命令来设置一下 LDFLAGS、CFLAGS、CPPFLAGS 好了。但是这里就很奇怪,正点原子官方教程用的是 arm-poky-linux-gnueabi-gcc 这个交叉编译工具链,不通过 export 命令设置那三个编译参数也能正常编译完成,我用 arm-linux-gnueabihf-gcc 就会出现找不到库的情况,没搞明白,后面搞明白了再补充。

shell
export CC=arm-linux-gnueabihf-gcc
export LDFLAGS="-L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib"
export CFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include"
export CPPFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include"

./configure --prefix=/home/sumu/9arm-linux-lib/freetype-2.8/freetype_out/ --host=arm-linux-gnueabihf --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib" ZLIB_LIBS=-lz LIBPNG_CFLAGS="-I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib" LIBPNG_LIBS=-lpng

这个配置命令很长,简单地提一下,具体的细节大家可以执行 "./configure --help" 查看配置帮助信息。

--prefix 选项指定 FreeType 库的安装目录; --host 选项设置为交叉编译器名称的前缀。

--with-zlib = yes 表示使用 zlib;

--with-bzip2 = no 表示不使用 bzip2 库;

--with-png = yes 表示使用 libpng 库;

--with-harfbuzz = no 表示不使用 harfbuzz 库。

ZLIB_CFLAGS 选项用于指定 zlib 的头文件路径和库文件路径,根据实际安装路径填写;

ZLIB_LIBS 选项指定链接的 zlib 库的名称;

LIBPNG_CFLAGS 选项用于指定 libpng 的头文件路径和库文件路径,根据实际安装路径填写;

LIBPNG_LIBS 选项用于指定链接的 libpng 库的名称。

配置完毕的时候这两个应该是开启的:

image-20241015074608820
  • 编译
shell
make

如果配置前没有加这几句的话,并且使用的是 arm-linux-gnueabihf-gcc:

shell
export LDFLAGS="-L/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/lib -L/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/lib"
export CFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include"
export CPPFLAGS="-I/home/sumu/9arm-linux-lib/zlib-1.2.10/zlib_out/include -I/home/sumu/9arm-linux-lib/libpng-1.6.44/libpng_out/include"

应该会报这个错误:

image-20241015074949082

要是加了上面三个配置项,还是用 arm-linux-gnueabihf-gcc,就没问题了:

image-20241015075719592
  • 安装
shell
make install

安装完毕后,我们会得到下面的文件:

image-20241014230718118

首先我们把看一下交叉编译成功了没,看一下动态库文件的格式:

shell
file libfreetype.so.6.14.0
image-20241014230614350

我们也顺便看一下有没有超链接,在拷贝的时候注意一下:

shell
sumu@sumu-virtual-machine:~/9arm-linux-lib/freetype-2.8/freetype_out$ tree
.
├── bin
│   └── freetype-config
├── include
│   └── freetype2
│       ├── freetype
│       │   ├── config
│       │   │   ├── ftconfig.h
│       │   │   ├── ftheader.h
│       │   │   ├── ftmodule.h
│       │   │   ├── ftoption.h
│       │   │   └── ftstdlib.h
│       │   # 此处省略一些头文件的显示
│       └── ft2build.h
├── lib
│   ├── libfreetype.a
│   ├── libfreetype.la
│   ├── libfreetype.so -> libfreetype.so.6.14.0
│   ├── libfreetype.so.6 -> libfreetype.so.6.14.0
│   ├── libfreetype.so.6.14.0
│   └── pkgconfig
│       └── freetype2.pc
└── share
    ├── aclocal
    │   └── freetype2.m4
    └── man
        └── man1
            └── freetype-config.1

11 directories, 61 files

会发现 lib 目录下有两个软链接,拷贝的时候需要注意一下。

3. 拷贝到共享目录

shell
cp -avf ~/9arm-linux-lib/freetype-2.8/freetype_out ~/1sharedfiles/linux_develop/imx6ull-app-demo/lib/freetype-2.8
cd ~/1sharedfiles/linux_develop/imx6ull-app-demo/lib/freetype-2.8/lib
cp libfreetype.so.6.14.0 libfreetype.so
cp libfreetype.so.6.14.0 libfreetype.so.6

4. 移植到开发板

先拷贝到 nfs 服务器目录:

shell
cp -a ~/9arm-linux-lib/freetype-2.8/freetype_out ~/4nfs/freetype-2.8

然后在串口终端,进入到 freetype 安装目录,将 lib 目录下的所有库文件拷贝到 Linux 系统/usr/lib 目录,注意在拷贝之前,先将开发板出厂系统中已经移植好的 zlib 库文件删除,执行下面这条命令:

shell
# 先备份删除的文件
cd /usr/lib
ls -alh libfreetype.*
tar -czf libfreetype_usr_lib.bk.tar.gz libfreetype.*
mv libfreetype_usr_lib.bk.tar.gz ~/nfs_temp/

rm -rf /usr/lib/libfreetype.*

删除之后,再将编译得到的 freetype 库文件拷贝到开发板/usr/lib 目录,拷贝库文件时,需要注意符号链接的问题,不能破坏原有的符号链接。

shell
cp -avf ~/nfs_temp/freetype-2.8/lib/libfreetype.* /usr/lib

拷贝完毕后检查一下软链接:

shell
ls -alh /usr/lib/libfreetype*
image-20241015230033213