LV18-01-LCD应用编程-06-FreeType简介
本文主要是LCD应用编程——FreeType简介的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
PC端开发环境 | Windows | Windows11 |
Ubuntu | Ubuntu20.04.2的64位版本 | |
VMware® Workstation 17 Pro | 17.6.0 build-24238078 | |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) | |
Win32DiskImager | Win32DiskImager v1.0 | |
Linux开发板环境 | Linux开发板 | 正点原子 i.MX6ULL Linux 阿尔法开发板 |
uboot | NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03) | |
linux内核 | linux-4.15(NXP官方提供) |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.nxp.com.cn/ | NXP官方网站 | |
https://www.nxpic.org.cn/ | NXP 官方社区 | |
https://u-boot.readthedocs.io/en/latest/ | u-boot官网 | |
https://www.kernel.org/ | linux内核官网 | |
其他网站 | kernel - Linux source code (v4.15) - Bootlin | linux内核源码在线查看 |
点击查看相关文件下载
分类 | 网址 | 说明 |
NXP | https://github.com/nxp-imx | NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库 |
https://elixir.bootlin.com/linux/latest/source | 在线阅读linux kernel源码 | |
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
I.MX6ULL | i.MX 6ULL Applications Processors for Industrial Products | I.MX6ULL 芯片手册(datasheet,可以在线查看) |
i.MX 6ULL Applications ProcessorReference Manual | I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网) |
一、LCD显示字符的方式?
1. 原始方式——取模
LCD 显示屏是由 width * height 个像素点构成的,显示字符,一个非常容易想到的方法便是对字符取模,然后在 LCD 屏上打点显示字符;以前学习过单片机的话,应该会接触过一些显示屏,如 oled、 或者其它一些点阵式的显示屏, 其实这些显示屏显示字符的原理都是一样的,如下所示:
我们可以通过一些字符取模软件获取到字符的子模; 所谓字模,其实就是一个二维数组, 用于表示字符点阵中,哪些小方块应该要填充颜色、哪些小方块不填充颜色。如上图“正”字符点阵,这是一个宽度为64(64 个小方块)、高度为 86(86 个小方块)的字符点阵, 我们会使用一个二维数组来表示这个字符点阵:
1 | unsigned char arr[86][8]; |
也就是一个 86 行 8 列的 unsigned char 类型数组, 数组存储的其实就是字符的位图数据, 字符点阵中的每一个小方块对应一个 bit 位,因为一行一共有 64 个小方块、也就对应 8 个字节(8 * 8 = 64); 将填充颜色的方块使用 1 表示、不填充颜色的方块使用 0 来表示,所以一个小方块刚好可以使用一个 bit 位来描述。
2. 有没有其他方式?
使用取模显示那种方式还是非常简单地,自己取模、自己写函数打点显示,但是取模很麻烦!实际的应用项目一般肯定不会这么干,除非我们的程序就是显示那么几个固定的字符。
操作系统中通常都会有很多的字体文件,如 Windows 系统“C:\Windows\Fonts”目录下就有很多的字体文件,如下所示:
字体文件的格式也有很多种,如 otf、 ttf、 ttc 等,这里就不列举了,有兴趣可以自己百度一下; Linux 系统中, 字体文件通常会放在/usr/share/fonts 目录下,
有了字体文件之后,我们就不需要再对字符进行取模了,它们已经编码进了字体文件中,我们只需要解析字体文件、访问字体文件,从字体文件中读取出字符的位图数据即可!
当然,这些复杂的解析过程并不需要我们自己去实现,有很多开源的字体引擎可以帮助我们来处理这些复杂的解析过程,如 freetype库。
3. 矢量字体
使用点阵字库显示英文字母、汉字时, 大小固定, 如果放大缩小则会模糊甚至有锯齿出现,为了解决这个问题,引用矢量字体。矢量字体形成分三步:
第1步 确定关键点(有些解释为字形,都是一个意思啦),
第2步 使用数学曲线( 贝塞尔曲线) 连接头键点,
第3步 填充闭合区线内部空间。
什么是关键点?以字母“ A”为例,它的的关键点如下图中的黄色所示。
再用数学曲线(比如贝塞尔曲线)将关键点都连接起来, 得到一系列的封闭的曲线,如下图所示:
最后把封闭空间填满颜色,就显示出一个 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),我在本地也下载了一份:freetype使用详解(中文).pdf
我们也可以下载每一个版本的文档:Index of /releases/freetype/ (gnu.org)
像这些带有doc的,都是对应版本的官方文档。下载后解压,主要可以看这个目录:
三、FreeType库移植
1. 下载源码
我们到这里下载:Index of /releases/freetype/ (gnu.org)
正点原子出厂系统中的事2.6版本,这里选2.8版本,由于是第一次用,防止踩坑,和教程采用同一个版本。下载完毕后解压:
1 | tar xf freetype-2.8.tar.gz |
2. 编译源码
- 创建安装目录
1 | mkdir -p /home/sumu/9arm-linux-lib/freetype-2.8/freetype_out |
- 配置编译选项
FreeType 库基于模块化设计,意味着我们可以对其进行裁剪,将不需要的功能模块从配置中移除,减小库文件的体积;除此之外,
FreeType 还支持很多配置选项, 如果想要对 FreeType 做一些自定义配置或者对其进行裁剪,可以参考 FreeType 源码目录下 docs/CUSTOMIZE 文档,该文件对此有比较详细的说明,建议看一看,如果有需求的话。 docs 目录下还有其它很多的说明文档, 也都可以看一看。
这里我们简单地配置一下,打开 include/freetype/config/ftoption.h 文件:
1 | vim include/freetype/config/ftoption.h |
该文件定义了很多的配置宏,我们可以选择使能或禁用这些配置选项,具体配置哪些功能,根据自己的需求来就是了,每一个配置宏都有详细地解释说明。 这里我们打开以下两个配置宏:
1 |
我们找到这两个宏,默认情况下,这两个都被注释掉了,所以是没有使能的; 把这两个宏的注释去掉,使能这两个配置宏。 但是我后来发现这里其实没必要注释掉,配置完之后会自动打开的,编译选项中是有这两个宏的:
1 | sumu@sumu-virtual-machine:~/9arm-linux-lib/freetype-2.8$ make |
第一个配置宏表示使用系统安装的 zlib 库,因为 FreeType 支持 Gzip 压缩文件,会使用到 zlib 库, zlib之前我们移植好了;第二个配置宏表示支持 PNG bitmap 位图,因为 FreeType 可以加载 PNG 格式的彩色位图字形,需要依赖于 libpng 库,这个库前面我们也是移植好了。
配置好之后,保存、退出 ftoption.h 文件,接着执行如下命令对 FreeType 工程源码进行配置按理来说下面的配置应该就可以了:
1 | ./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 |
但是,这样配置的话,编译器无法生效:
要通过export来设置CC环境变量才行:
1 | export CC=arm-linux-gnueabihf-gcc |
但是这个时候最后编译会报找不到zlib和png的库,不是很清楚原因是什么,就暂时先通过export命令来设置一下LDFLAGS、CFLAGS、CPPFLAGS好了。但是这里就很奇怪,正点原子官方教程用的是 arm-poky-linux-gnueabi-gcc 这个交叉编译工具链,不通过export命令设置那三个编译参数也能正常编译完成,我用arm-linux-gnueabihf-gcc就会出现找不到库的情况,没搞明白,后面搞明白了再补充。
1 | export CC=arm-linux-gnueabihf-gcc |
这个配置命令很长,简单地提一下,具体的细节大家可以执行”./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 库的名称。
配置完毕的时候这两个应该是开启的:
- 编译
1 | make |
如果配置前没有加这几句的话,并且使用的是arm-linux-gnueabihf-gcc:
1 | 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" |
应该会报这个错误:
要是加了上面三个配置项,还是用arm-linux-gnueabihf-gcc,就没问题了:
- 安装
1 | make install |
安装完毕后,我们会得到下面的文件:
首先我们把看一下交叉编译成功了没,看一下动态库文件的格式:
1 | file libfreetype.so.6.14.0 |
我们也顺便看一下有没有超链接,在拷贝的时候注意一下:
1 | sumu@sumu-virtual-machine:~/9arm-linux-lib/freetype-2.8/freetype_out$ tree |
会发现lib目录下有两个软链接,拷贝的时候需要注意一下。
3. 拷贝到共享目录
1 | cp -avf ~/9arm-linux-lib/freetype-2.8/freetype_out ~/1sharedfiles/linux_develop/imx6ull-app-demo/lib/freetype-2.8 |
4. 移植到开发板
先拷贝到nfs服务器目录:
1 | cp -a ~/9arm-linux-lib/freetype-2.8/freetype_out ~/4nfs/freetype-2.8 |
然后在串口终端,进入到 freetype 安装目录,将 lib 目录下的所有库文件拷贝到 Linux 系统/usr/lib 目录,注意在拷贝之前,先将开发板出厂系统中已经移植好的zlib库文件删除,执行下面这条命令:
1 | 先备份删除的文件 |
删除之后,再将编译得到的 freetype 库文件拷贝到开发板/usr/lib 目录,拷贝库文件时,需要注意符号链接的问题,不能破坏原有的符号链接。
1 | cp -avf ~/nfs_temp/freetype-2.8/lib/libfreetype.* /usr/lib |
拷贝完毕后检查一下软链接:
1 | ls -alh /usr/lib/libfreetype* |