freetype之PC机体验
title: freetype之PC机体验
date: 2019/03/03 00:07:56
toc: true
freetype之PC机体验
引入
本节代码仓库 https://gitee.com/layty/project_for_linux/tree/master/02-freetype
一个完整的字体库由两个部分组成
- charmap 编码,也就是索引,通过指定的编码找到具体要显示的字形,一个字体可能支持多种编码
- glyph字形,这里指的是如何去描绘(比如贝塞尔曲线)这个具体的文字
中文教程
官方教程
- 1. Header Files
- 2. Library Initialization
- 3. Loading a Font Face
- 4. Accessing the Face Data
- 5. Setting the Current Pixel Size
- 6. Loading a Glyph Image
- 7. Simple Text Rendering
- 1. Glyph Metrics
- 2. Managing Glyph Images
- 3. Global Glyph Metrics
- 4. Simple Text Rendering: Kerning and Centering
- 5. Advanced Text Rendering: Transformation and Centering and Kerning
- 6. Accessing Metrics in Design Font Units, and Scaling Them
- Conclusion
代码结构
API手册
II. Public Objects and Classes
- 1. Object Orientation in FreeType 2
- 2. The
FT_Library
class - 3. The
FT_Face
class - 4. The
FT_Size
class - 5. The
FT_GlyphSlot
class - 6. The
FT_CharMap
class - 7. Objects Relationship
III. Internal Objects and Classes
字体概念
PC上安装
#解压
tar xjf freetype-2.4.10.tar.bz2
#重命名
mv freetype-2.4.10 freetype-2.4.10_pc
#配置
cd freetype-2.4.10_pc/
./configure
#编译
make
#安装到根目录 /usr/local/
sudo make install
book@100ask:~/stu/repo/demo_tar/freetype-2.4.10_pc$ ls /usr/local/lib/
libfreetype.a libfreetype.so libfreetype.so.6.9.0 python2.7
libfreetype.la libfreetype.so.6 pkgconfig python3.5
book@100ask:~/stu/repo/demo_tar/freetype-2.4.10_pc$ ls /usr/local/include/
freetype2 ft2build.h
官方例子
例子在freetype-doc-2.4.10.tar.bz2\freetype-2.4.10\docs\tutorial
,直接编译报错缺少头文件
In file included from example1.c:11:0:
/usr/local/include/ft2build.h:56:38: fatal error: freetype/config/ftheader.h: 没有那个文件或目录
compilation terminated.
但实际上local
下是有这个文件的
ls /usr/local/include/freetype2/freetype/config
ftconfig.h ftheader.h ftmodule.h ftoption.h ftstdlib.h
我们可以编译的时候用-I
指定头文件路径
# gcc -o example example1.c -I /usr/local/include/freetype2
/tmp/ccNUBZti.o:在函数‘main’中:
example1.c:(.text+0x25b):对‘FT_Init_FreeType’未定义的引用
example1.c:(.text+0x284):对‘FT_New_Face’未定义的引用
example1.c:(.text+0x29d):对‘FT_Set_Pixel_Sizes’未定义的引用
example1.c:(.text+0x2c4):对‘cos’未定义的引用
example1.c:(.text+0x2f5):对‘sin’未定义的引用
example1.c:(.text+0x332):对‘sin’未定义的引用
example1.c:(.text+0x363):对‘cos’未定义的引用
example1.c:(.text+0x3b6):对‘FT_Set_Transform’未定义的引用
example1.c:(.text+0x3de):对‘FT_Load_Char’未定义的引用
example1.c:(.text+0x465):对‘FT_Done_Face’未定义的引用
example1.c:(.text+0x471):对‘FT_Done_FreeType’未定义的引用
collect2: error: ld returned 1 exit status
这里提示没有库文件,这里需要使用-l直接库的名字没有空格
#gcc -o example example1.c -I /usr/local/include/freetype2 -lfreetype
/tmp/cchpuAJt.o:在函数‘main’中:
example1.c:(.text+0x2c4):对‘cos’未定义的引用
example1.c:(.text+0x2f5):对‘sin’未定义的引用
example1.c:(.text+0x332):对‘sin’未定义的引用
example1.c:(.text+0x363):对‘cos’未定义的引用
collect2: error: ld returned 1 exit status
这里提示没有数学库,这里加上-lm
,m表示数学
# gcc -o example example1.c -I /usr/local/include/freetype2 -lfreetype -lm
运行之后提示帮助,需要一个字体文件,可以去win
下的C:\Windows\Fonts
找到新宋体
$ ./example
usage: ./example font sample-text
这里发现屏幕看的不是很清楚,主要是因为程序里设置了显示的分辨率,也就是一行出现640个点
#define WIDTH 640
#define HEIGHT 480
我们这里修改下大小,同时取消字体的旋转,否则也显示不出来
#define WIDTH 80 #横向80个点
#define HEIGHT 90 #纵向90个点
同时也要修改显示的位置
/* the pen position in 26.6 cartesian space coordinates; */
/* start at (0,40) relative to the upper left corner */
pen.x = 0 * 64;
pen.y = ( target_height - 40 ) * 64;
angle = (0.0 / 360 ) * 3.14159 * 2; /* 取消旋转*/
这个实验有时候在mobaxtem
中显示不太好,可以保存到文件然后去查看
./example simsun.ttc 123
# 保存到文件看
./example simsun.ttc 123 >123.txt
宽字符保存显示中文
我们以前是这么保存中文的,这里处理的时候需要判断是中文,则取两个字符,如果是英文取出一个字符,非常不方便,所以这里引入了宽字符的概念,注意:wchar_t在windows占2byte,在linux占4bytes.
char * str1="中文and english"
#include <stdio.h>
#include <wchar.h>
int main(int argc,char *argv[])
{
int i;
wchar_t* chinese_str = L"中文123";
unsigned int *p =(wchar_t*)chinese_str;
for(i=0;i<wcslen(chinese_str);i++)
{
printf("0x%x ",p[i]);
}
printf("\n");
}
打印显示是unicode编码
$ ./a.out
0x4e2d 0x6587 0x31 0x32 0x33
我这里保存的是utf-8
的格式,如果保存的是gbk的,则需要加上指定输入文件编码
-finput-charset=GBK
接着我们用freetype打印中文,加上这里的代码
for ( n = 0; n < wcslen(chinese_str); n++ )
{
error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );
}
坐标框架体系
上面我们设置了字体是24*24
像素的大小,那么它实际上怎么显示的呢,这里我们在代码上加入打印坐标
void show_image( void )
{
int i, j;
for ( i = 0; i < HEIGHT; i++ )
{
printf("%02d",i);
for ( j = 0; j < WIDTH; j++ )
putchar( image[i][j] == 0 ? ' ': image[i][j] < 128 ? '+': '*' );
putchar( '\n' );
}
}
我们再来看下我们是怎么设置显示位置的,位置是在(0,40)显示的
FT_Set_Pixel_Sizes(face,24,0)
/* the pen position in 26.6 cartesian space coordinates; */
/* start at (0,40) relative to the upper left corner */
pen.x = 0 * 64;
pen.y = ( target_height - 40 ) * 64;
但是很明显原点并不在这里
为什么会这样,并且可以看出来,字符显示会到原点的下方?
可以这么理解,我们先看下如下的字母,gpq
等都在下方有显示,上图也能看出a的左下起始也是在横轴40的位置左右,实际上我们可以理解为基线.
为了兼容中文英文以及其他字符,实际的画图是下面这样的
advance有横向的也有纵向的数值,比如斜着的时候
具体的代码我们是这么体现的,在写一个字符的时候
slot = face->glyph;
....
/* increment pen position */
pen.x += slot->advance.x;
pen.y += slot->advance.y;
字符坐标信息获取
那么我们如何得到字符的其他信息,比如ymax
等,参考文档tutorial
中可以看到Measuring the Glyph Image
章节
FT_EXPORT( void )
FT_Glyph_Get_CBox( FT_Glyph glyph,
FT_UInt bbox_mode,
FT_BBox *acbox );
注意第一个参数是FT_Glyph
,而我们之前是使用FT_GlyphSlot
来转换成位图的.
注意 我们提取本次字符的形状数据后,也就是获得字形槽后,上次的字形槽数据就被冲掉了,那么我们如何去获取上次的字形数据呢?
#include FT_GLYPH_H
FT_Glyph glyph; /* a handle to the glyph image */
...
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NORMAL );
if ( error ) { ... }
error = FT_Get_Glyph( face->glyph, &glyph ); //从之前的插槽中取出FT_Glyph
if ( error ) { ... }
//--------实际代码如下--------------------------------------------
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
/* now, draw to our target surface (convert position) */
error = FT_Get_Glyph( face->glyph, &glyph );
if (error) {
printf("load from face->glyph is failed\n");
return -1;
}
FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox );
printf("\n\nunicode is %x\n",chinese_str[n]);
printf("lcd offset is [x]=%d,[y]=%d\n",slot->bitmap_left,target_height - slot->bitmap_top);
printf("[pen.x]=%ld,[pen.y]=%ld\n",pen.x/64,pen.y/64);
printf("glyph [xMin]=%ld,[yMin]=%ld,[xMax]=%ld,[ymax]=%ld\n",bbox.xMin,bbox.yMin,bbox.xMax,bbox.yMax);
printf("advance.x/64=%ld,y.advance/64=%ld\n",slot->advance.x/64,slot->advance.y/64);// unit is 1/64 pixel
我们可以打印出来看一下,这里加入笛卡尔的坐标打印
可以看出来这里的韦字宽度是23
,有点奇怪不是24
哈哈 不过也是在框里的
下一个字符的原点就是上一个字符的原点加上一个字符的advance
# 韦的宽度是23长度是24
unicode is 97e6
lcd offset is [x]=1,[y]=20
[pen.x]=0,[pen.y]=50
glyph [xMin]=1,[yMin]=47,[xMax]=23,[ymax]=70
advance.x/64=24,y.advance/64=0
unicode is 4e2d
lcd offset is [x]=27,[y]=20
[pen.x]=24,[pen.y]=50
glyph [xMin]=27,[yMin]=47,[xMax]=46,[ymax]=70
advance.x/64=24,y.advance/64=0
# a字母的宽度是12,长度是12
unicode is 61
lcd offset is [x]=49,[y]=29
[pen.x]=48,[pen.y]=50
glyph [xMin]=49,[yMin]=50,[xMax]=60,[ymax]=61
advance.x/64=12,y.advance/64=0
freetype之PC机体验的更多相关文章
- 基于X86平台的PC机通过网络发送一个int(32位)整数的字节顺序
1.字节顺序 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端.大端两种字节顺序.小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处:大端字节序是高字节数据存 ...
- 建立开发板与PC机之间的nfs服务器
ARM开发板与PC通过NFS 网络文件系统挂接,很方便文件的移动,也为我们的开发带来了方便.接下来,我就详细的介绍下如何建立ARM与PC机的挂接. 我是用的UBuntu系统. 首先,我们需要在主机上安 ...
- intel 系列的PC机处理器是大端的还是小端的?
intel 系列的PC机处理器是大端的还是小端的?由于要安装oracle,需要知道是大端机器还是小端的,你好,现在流行的PC,是微型处理器,也就是所谓的小端处理器. 大端处理器是由若干个微型处理器有机 ...
- php或js判断网站访问者来自手机或者pc机
php或js判断网站访问者来自手机或者pc机 2013年9月26日,在弄wtuonline的时候为了区分用户是来自手机版浏览器还是pc,针对不同平台选择不同的网站版本,最终总结如下: ...
- 浅析PC机串口通讯流控制
转自浅析PC机串口通讯流控制 我们在串行通讯处理中,常常看到RTS/CTS和XON/XOFF这两个选项,这就是两个流控制的选项,目前流控制主要应用于调制解调器的数据通讯中,但对普通RS232编程,了解 ...
- 开发板-PC机(宿主机)-虚拟机(VM)之间网络通信设置方法及须要注意的问题
1.不使用路由器交换机 硬件连接: 使用网线将开发板和PC机相连 串口线将PC机和开发板相连 使用命令: ifconfig -a 串口控制端查看开发板的网络配置 route -n 串口控制端查看开发板 ...
- pc机进入android的shell
一直都知道自己非常死板,刚刚再一次验证了.. 下载下来android开发必备的工具之后,就按部就班的一步步的来了.没想过这些工具有没有其它用处,更有甚者,在刚開始接触android的时候.居然不知道自 ...
- 【转】在嵌入式Linux和PC机Linux下使用popen函数时,程序运行结果有差异。
下面程序演示了在嵌入式Linux和PC机Linux下使用popen函数时,程序的运行结果是有差异的. 两个程序 atest.c 和 btest.c,atest 检查是否有 btest 进程运行,如果没 ...
- 基于C/S模式的android手机与PC机通信系统的开发
原文链接: http://blog.csdn.net/nupt123456789/article/details/8213486 基于C/S模式的android手机与PC机通信系统的开发 作者:郑海波 ...
随机推荐
- Your project path contains non-ASCII characters
Android studio导入project时报错 non-ASCII characters意味着中文字符报错,解决方法简单有效: 检查项目路径中是否出现中文名,将中文字符修改成英文就可以解决辽~
- 问题解决--无法解析的外部符号 _imp_XXXXXXXXX
错误示例: 出现字符_imp,说明不是真正的静态库,而是某个动态库的导入库,导入函数和自己不同名,所以加了字符_imp.比如说_imp_GetUserNameA就是GetUserNameA函数. 会报 ...
- Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式 目录 Pycharm使用技巧(转载) Python第一天 安装 shell 文件 Py ...
- [转]Lua和Lua JIT及优化指南
一.什么是lua&luaJit lua(www.lua.org)其实就是为了嵌入其它应用程序而开发的一个脚本语言, luajit(www.luajit.org)是lua的一个Just-In-T ...
- 性能测试中TPS上不去的几种原因浅析
转:https://www.cnblogs.com/imyalost/p/8309468.html 下面就说说压测中为什么TPS上不去的原因: 1.网络带宽 在压力测试中,有时候要模拟大量的用户请求, ...
- pip "Cannot uninstall 'six'. It is a distutils installed project..." 解决方法
安装 mysql-connector-python 时,由于依赖包 six 之前已经安装过,但是不能自动更新到所需版本.有如下错误提示: pip "Cannot uninstall 'six ...
- 在Winform系统界面中对进展阶段的动态展示和处理
在我们做客户关系管理系统的Winform界面的时候,需要对进展阶段这个属性进行一个方便的动态切换和标记处理,如我们根据不同的进展阶段显示不同的相关信息,也可以随时保存当前的阶段信息.其实也是一个比较常 ...
- 501. Find Mode in Binary Search Tree
Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred ...
- Linux系统下Mysql安装与配置
一,使用系统 Centos7: 在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB. 二,下载安装 ...
- 转载:img是什么元素?置换元素?
转载: https://blog.csdn.net/kingliguo/article/details/52643594 img是什么元素? 应是行内元素,判断一个元素是行内元素,还是块元素,无非就是 ...