im6ull学习总结(三-4)freetype显示单个字体

矢量字体引入

使用点阵字库显示英文字母、汉字时,大小固定,如果放大缩小则会模糊甚至有锯齿出现,为了解决这个问题,引用矢量字体。
矢量字体形成分三步:
第1步 确定关键点,
第2步 使用数学曲线(贝塞尔曲线)连接头键点,
第3步 填充闭合区线内部空间。
什么是关键点?以字母“A”为例,它的的关键点如图 6.16 中的黄色所示。
在这里插入图片描述
再用数学曲线(比如贝塞尔曲线)将关键点都连接起来,得到一系列的封闭的曲线
在这里插入图片描述
最后把封闭空间填满颜色,就显示出一个 A 字母,
6

freetype如何描写字符

Freetype 是开源的字体引擎库,它提供统一的接口来访问多种字体格式文件,从而实现矢量字体显示。我们只需要移植这个字体引擎,调用对应的 API 接口,提供字体文件,就可以让 freetype 库帮我们取出关键点、实现闭合曲线,填充颜色,达到显示矢量字体的目的。
关 键 点 (glyph) 存 在 字 体 文 件 中 , Windows 使 用 的 字 体 文 件 在c:\Windows\Fonts 目录下,扩展名为 TTF 的都是矢量字库,本次使用实验使用的是新宋字体 simsun.ttc。
给定一个字符,怎么在字体文件中找到它的关键点?
首先要确定该字符的编码值:比如 ASCII 码、GB2312 码、UNICODE 码。如果字体文件支持某种编码格式(charset),就可以使用这类编码值去找到该字符的关键点(glyph)。有些字体文件支持多种编码格式(charset),这在文件中被称为 charmaps(注意:这个单词是复数,意味着可能支持多种 charset)
首先要确定该字符的编码值:比如 ASCII 码、GB2312 码、UNICODE 码。如果字体文件支持某种编码格式(charset),就可以使用这类编码值去找到该字符的关键点(glyph)。有些字体文件支持多种编码格式(charset),这在文件中被称为 charmaps(注意:这个单词是复数,意味着可能支持多种 charset)
在这里插入图片描述
Charmaps 表示字符映射表,字体文件可能支持哪一些编码,GB2312、UNICODE、BIG5 或其他。如果字体文件支持该编码,使用编码值通过 charmap 就可以找到对应的 glyph,一般而言都支持 UNICODE 码。
一个文字的显示过程可以概括如下:
1、给定一个字符可以确定它的编码值(ASCII、UNICODE、GB2312)
2、设置字体大小;
3、根据编码值,从文件头部中通过 charmap 找到对应的关键点(glyph),它会根据字体大小调整关键点;
4、把关键点转换为位图点阵;
5、在 LCD 上显示出来

如何使用 freetype库,总结出下列步骤:
1、初始化:FT_InitFreetype
2、加载(打开)字体 Face:FT_New_Face
3、设置字体大小:FT_Set_Char_Sizes 或FT_Set_Pixel_Sizes
4、选择 charmap:FT_Select_Charmap
5、根据编码值 charcode 找到 glyph_index:glyph_index = FT_Get_Char_Index(face,charcode)
6、根据 glyph_index 取出 glyph:FT_Load_Glyph(face,glyph_index)
7、转为位图:FT_Render_Glyph
8、移动或旋转:FT_Set_Transform
最后显示出来。
上面的⑤⑥⑦可以使用一个函数代替:FT_Load_Char(face, charcode, FT_LOAD_RENDER),它就可以得到位图。

在 LCD 上显示一个矢量字体

1、使用 wchar_t 获得字符的 UNICODE 值
要显示一个字符,首先要确定它的编码值。常用的是 UNICODE 编码,在程序里使用这样的语句定义字符串时,如char *str = “中”;str 中保存的要么是 GB2312 编码值,要么是UTF-8 格式的编码。即使编译时使用“-fexec-charset=UTF-8”,str 中保存的也不是直接能使用的 UNICODE 值:
如果想在代码中能直接使用 UNICODE 值,需要使用 wchar_t,宽字符。

#include <stdio.h>
#include <string.h>
#include <wchar.h>
int main (int argc,char **argv)
{//wchar_t是一种数据类型,用于表示宽字符或多字节字符,用于处理不限于ASCII字符集//wchar_t 会根据编译器的不同而分为两个字节和四个字节。// 定义了一个wchar_t类型的指针变量chinese_str他指向了L"中gif";其中L告诉编译器“中gif"是宽字符而不是普通字符串,普通字符串每个字符是一个char。//也就是说如果用wchar_t定义变量就要用L修饰字符串告诉编译器wchar_t *chinese_str = L"中gif";unsigned int *p = (wchar_t *)chinese_str;int i;printf("sizof(int)=%d, : \n",(int)sizeof(int));printf("sizof(wchar_t)=%d,str's Unicode : \n",(int)sizeof(wchar_t));for ( i = 0; i < wcslen(chinese_str); i++){printf("0x%x ",p[i]);}printf("\n");return 0;
}

运行结果
在这里插入图片描述
这里注意文件类型是utf-8格式
如果是GB2312 需要这样编译
gcc -finput-charset=GB2312 -fexec-charset=UTF-8 -o test_wchar test_wchar.c

使用freetype得到位图

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <sys/ioctl.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include <wchar.h>
int fd_fb;
struct fb_var_screeninfo  var;
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 red, green, blue;	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:{/* 565 */red   = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue  = (color >> 0) & 0xff;color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);*pen_16 = color;break;}case 32:{*pen_32 = color;break;}default:{printf("can't surport %dbpp\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;//printf("x = %d, y = %d\n", x, y);for ( j = y, q = 0; j < y_max; j++, q++ ){for ( i = x, p = 0; i < x_max; i++, p++ ){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]);//printf("buffer[%d]=%d \r\n",q * bitmap->width + p,bitmap->buffer[q * bitmap->width + p]);}}
}int main(int argc,char ** argv)
{wchar_t *chinese_str = L"繁";FT_Library library;FT_Face face;int error;FT_Vector pen;FT_GlyphSlot slot;int font_size = 24;if (argc < 2){/* 通过参数打印用法 */printf("Usage : %s <font_file> [font_size]\n", argv[0]);return -1;}if (argc == 3){//将字符串转换成ul(unsigned long)NULL表示没有使用额外的错误检验,0表示自动监测字符串的基数(也就是字符串的进制数)//./02_freetype_show_font ./simsun.ttc 150 这里 就将150字符串转成ulfont_size = strtoul(argv[2], NULL, 0);fd_fb = open("/dev/fb0",O_RDWR);}if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}line_width  = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;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\n");return -1;}/* 清屏: 全部设为黑色 */memset(fbmem, 0, screen_size);//1、FT_Init_FreeType(&library)的作用是将 FreeType 库初始化,//并将初始化后的库对象保存在 library 变量中。//如果初始化成功,FT_Init_FreeType() //函数会返回一个表示成功的错误码(通常是 0),//否则会返回一个表示失败的错误码error = FT_Init_FreeType(&library);//2、加载字体文件,保存在&face 中://FT_New_Face() 函数是用于创建一个新的字体面对象(font face)的函数。它接受以下参数://library一个已经初始化的 FreeType 库对象//argv[1]示字体文件路径的字符串,指定要加载的字体文件。//0:表示字体索引,通常为0,用于指定要加载的字体文件中的第几个字体,如果字体文件只包含一个字体,则索引为0。//face:一个指向 FT_Face 类型的指针,用于接收新创建的字体面对象//simsun.ttc是一种字体文件,它是宋体字体(SimSun)的TrueType集合文件(TrueType Collection)。error = FT_New_Face(library,argv[1],0,&face);//face 中获得 FT_GlyphSlot,后面的代码中文字的位图就是保存在 FT_GlyphSlot 里。slot = face->glyph;//face:要设置像素大小的字体面对象。//font_size:目标字体大小(以像素为单位)。//0:表示分辨率的水平方向值,通常为0,表示使用默认值//FT_Load_Char() 函数用于加载指定字符的字形数据。它接受以下参数://face:要加载字形数据的字体面对象。//chinese_str[0]:要加载的字符,通常是一个 Unicode 字符编码值(例如,中文字符的 Unicode 编码)。//FT_LOAD_RENDER:一个加载标志,表示要加载并渲染字形数据。//3、设置字体大小FT_Set_Pixel_Sizes(face, font_size, 0);//4、根据编码值得到位图使用 FT_Load_Char 函数,就可以实现这 3 个功能:// 根据编码值获得 glyph_index:FT_Get_Char_Index// 根据 glyph_idex 取出 glyph:FT_Load_Glyph// 渲染出位图:FT_Render_Glypherror = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );if (error){printf("FT_Load_Char error\n");return -1;}//draw_bitmap() 函数用于在指定位置绘制字形的位图数据draw_bitmap( &slot->bitmap,var.xres/2,var.yres/2);return 0;	
}

我们先分析一下流程
1、初始化freetype库
FT_Init_FreeType(&library)的作用是将 FreeType 库初始化这个库就保存在library中
2、加载字体文件,保存在&face 中:
3、设置字体大小
4、根据编码值得到位图使用 FT_Load_Char 函数,就可以实现这 3 个功能:

draw_bitmap( &slot->bitmap,var.xres/2,var.yres/2);
bitmap就是我们得到的位图的结构体如下图所示
一个像素对应一个字节的buffer
这样我们能确定字体的宽度和高度去顶像素点个数(多少行多少列)
然后使用两个for循环处理每一个像素点将buffer中的值作为color传入lcd_put_pixel中
如果buffer中有值(非零)color就会给framebuffer映射的内存中赋值;但是由于只有一个字节var.bits_per_pixel是32也就是0x00rrggbb格式我们只能给bb值所以最终显示字体颜色为蓝色。、
在这里插入图片描述

这是一部分buffer值。
在这里插入图片描述
这里我们完成显示单个字体下面完成字体变换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/235487.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

正则表达式的语法

如果要想灵活的运用正则表达式&#xff0c;必须了解其中各种元素字符的功能&#xff0c;元字符从功能上大致分为&#xff1a; 限定符 选择匹配符 分组组合和反向引用符 特殊字符 字符匹配符 定位符 我们先说一下元字符的转义号 元字符(Metacharacter)-转义号 \\ \\ 符号…

【K8S 存储卷】K8S的存储卷+PV/PVC

目录 一、K8S的存储卷 1、概念&#xff1a; 2、挂载的方式&#xff1a; 2.1、emptyDir&#xff1a; 2.2、hostPath&#xff1a; 2.3、NFS共享存储&#xff1a; 二、PV和PVC&#xff1a; 1、概念 2、请求方式 3、静态请求流程图&#xff1a; 4、PV和PVC的生命周期 5、…

【分布式】分布式链路跟踪技术

为什么需要分布式链路追踪 提到分布式链路追踪&#xff0c;我们要先提到微服务。相信很多人都接触过微服务。微服务是一种开发软件的架构和组织方法&#xff0c;它侧重将服务解耦&#xff0c;服务之间通过API通信。使应用程序更易于扩展和更快地开发&#xff0c;从而加速新功能…

PiflowX-MysqlCdc组件

MysqlCdc组件 组件说明 MySQL CDC连接器允许从MySQL数据库读取快照数据和增量数据。 计算引擎 flink 组件分组 cdc 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子hostnameHostname“”无是MySQL…

机器学习周刊 第4期:动手实战人工智能、计算机科学热门论文、免费的基于ChatGPT API的安卓端语音助手、每日数学、检索增强 (RAG) 生成技术综述

LLM开发者必读论文&#xff1a;检索增强&#xff08;RAG&#xff09;生成技术综述&#xff01; 目录&#xff1a; 1、动手实战人工智能 Hands-on Al2、huggingface的NLP、深度强化学习、语音课3、Awesome Jupyter4、计算机科学热门论文5、LLM开发者必读论文:检索增强 (RAG) 生…

工业智能网关如何保障数据通信安全

工业智能网关是组成工业物联网的重要设备&#xff0c;不仅可以起到数据交换、通信、边缘计算的功能&#xff0c;还可以发挥数据安全保障功能&#xff0c;保障工业物联网稳定、可持续。本篇就为大家简单介绍一下工业智能网关增强和确保数据通信安全的几种措施&#xff1a; 1、软…

UE4 4.21-4.27使用编辑器蓝图EditorBlueprint方法

在UE4 4.21中&#xff0c;编辑器蓝图&#xff08;Editor Blueprint&#xff09;是一个强大的工具&#xff0c;允许开发者扩展和自定义Unreal编辑器的功能。通过编辑器蓝图&#xff0c;我们可以创建自定义的工具和功能&#xff0c;以优化开发流程。 本教程将指导您如何在UE4 4.…

如何顺滑使用华为云编译构建平台?

这两年平台构建服务需求越来越大&#xff0c;却一直苦于找不到一些指南&#xff0c; 这里特意写了一篇&#xff0c; 对在学习代码阶段和新手程序员朋友也蛮友好&#xff0c; 配置真的也不难&#xff0c; 也特别适合想尝试从0到1做个APP的朋友了。 以华为云的CodeArts Build为例…

mysql服务多实例运行

1、官网下载mysql安装包 https://downloads.mysql.com/archives/community/ 2、解压安装包 tar -zxvf mysql-8.1.0-linux-glibc2.28-aarch64.tar.xz -C /usr/localmv /usr/local/mysql-8.1.0-linux-glibc2.28-aarch64 /usr/local/mysql 3、创建mysql用户组 groupadd…

Js--数组(三)

1.什么是数组&#xff1f; 数组&#xff1a;(Array)是一种可以按顺序保存数据的数据类型 2.为什么要数组&#xff1f; 思考&#xff1a;如果我想保存一个班里所有同学的姓名怎么办&#xff1f; 场景&#xff1a;如果有多个数据可以用数组保存起来&#xff0c;然后放到一个变量…

Live800:客户服务中的AI辅助培训与员工成长

随着科技的发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经广泛应用于各个行业&#xff0c;其中包括客户服务领域。以下是关于如何运用AI技术辅助客服人员进行培训和学习&#xff0c;提高员工的专业素质和服务能力的详细探讨。 一、AI在客户服务中的应用 AI技术在…

安卓版本与鸿蒙将不再兼容,鸿蒙工程师究竟有多抢手?

年薪最高160万&#xff01; 鸿蒙工程师究竟有多抢手&#xff1f; 套壳安卓”的质疑言犹在耳&#xff0c;如今华为正在计划将鸿蒙OS与安卓完全脱离。 此前&#xff0c;鸿蒙OS为了迅速扩大用户规模&#xff0c;采取了兼容安卓的策略。而如今&#xff0c;已有数亿设备搭载的鸿蒙…

短视频发展电商,哪个平台更占优势,新手如何选择?

我是电商珠珠 众所周知&#xff0c;自19年抖音开始发展短视频时&#xff0c;短短两年的时间&#xff0c;就将电商圈拉高了一个度。 20年是抖音发展的鼎盛时期&#xff0c;也是很多新手容易财富自由的时期&#xff0c;平台的各项红利都纷纷向商家靠拢。 如今已经发展了四年的…

Ubuntu22.04开机左上角下划线闪烁不开机

按下CtrlAltF2&#xff0c;打开TTY系统&#xff0c;然后通过用户名和密码登录&#xff0c;随后使用 sudo apt --fix-broken install 根据提示排除错误信息&#xff0c;然后使用apt安装lightdm安装就行。 tips:当使用EasyConnect的时候&#xff0c;你可能参考了下面这篇文章知…

中国京津冀国际光伏展

中国京津冀国际光伏展是一个为光伏行业搭建交流合作平台的国际展览会。该展览会主要展示光伏发电技术、光伏产品、光伏材料、光伏设备等相关领域的最新产品和技术。展会吸引了来自国内外光伏行业的企业、专家和观众参与&#xff0c;为他们提供了一个了解行业最新动态、展示自身…

Kafka之集群搭建

1. 为什么要使用kafka集群 单机服务下&#xff0c;Kafka已经具备了非常高的性能。TPS能够达到百万级别。但是&#xff0c;在实际工作中使用时&#xff0c;单机搭建的Kafka会有很大的局限性。 ​ 消息太多&#xff0c;需要分开保存。Kafka是面向海量消息设计的&#xff0c;一个T…

Linux 简述

文章目录 1. 背景2. Linux 环境搭建2.1 环境搭建方式2.2 使用云服务器2.3 使用终端软件连接到 Linux 3. Linux 常用命令3.1 ls3.2 cd3.3 pwd3.4 touch3.5 cat3.6 echo3.7 vim3.8 mkdir3.9 rm3.10 mv3.11 cp3.12 grep3.13 ps3.14 netstat 4. 搭建 Java 部署环境4.1 jdk4.2 tomca…

发表《Optics Express》玻色量子联合天津大学实现5比特全光量子随机数发生器

2023年11月&#xff0c;北京玻色量子科技有限公司&#xff08;以下简称“玻色量子”&#xff09;联合天津大学在学术期刊《Optics Express》上发表了以“5-bit all-optical quantum random number generator based on a time-multiplexed optical parametric oscillator”&…

使用 gitee+sphinx+readthedocs 搭建个人博客

给大家安利如何快速搭建个人博客网站&#xff01; 前言 这是我本地运行的一个使用sphinx构建的博客服务&#xff0c;这些文章&#xff0c;都是用markdown写的。 一直有个想法&#xff0c;就是把自己写的这些文件&#xff0c;搞成一个博客网站&#xff0c;放到网上&#xff0c…

Qt中QGraphicsView总体架构学习

前沿 前段时间学习了下如何在QGraphicsView架构中绘制刻度尺&#xff0c;主要是与OnPainter中进行比较的&#xff0c;那么今天就来详细讲解下我对QGraphicsView框架的认知吧~ 最近一段时间想学习下&#xff0c;如果我有不正确的&#xff0c;欢迎留言探讨哟~ QGraphicsView架…