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字形,这里指的是如何去描绘(比如贝塞尔曲线)这个具体的文字

中文教程

FreeType2 教程的第二部分

freetype使用详解(中文)

数据结构中文

官方教程

I. Simple Glyph Loading

II. Managing Glyphs

代码结构

API手册

I. Components and APIs

II. Public Objects and Classes

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,在linux4bytes.

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来转换成位图的.

注意 我们提取本次字符的形状数据后,也就是获得字形槽后,上次的字形槽数据就被冲掉了,那么我们如何去获取上次的字形数据呢?

参考 2. Managing Glyph Images

#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机体验的更多相关文章

  1. 基于X86平台的PC机通过网络发送一个int(32位)整数的字节顺序

    1.字节顺序 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端.大端两种字节顺序.小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处:大端字节序是高字节数据存 ...

  2. 建立开发板与PC机之间的nfs服务器

    ARM开发板与PC通过NFS 网络文件系统挂接,很方便文件的移动,也为我们的开发带来了方便.接下来,我就详细的介绍下如何建立ARM与PC机的挂接. 我是用的UBuntu系统. 首先,我们需要在主机上安 ...

  3. intel 系列的PC机处理器是大端的还是小端的?

    intel 系列的PC机处理器是大端的还是小端的?由于要安装oracle,需要知道是大端机器还是小端的,你好,现在流行的PC,是微型处理器,也就是所谓的小端处理器. 大端处理器是由若干个微型处理器有机 ...

  4. php或js判断网站访问者来自手机或者pc机

    php或js判断网站访问者来自手机或者pc机 2013年9月26日,在弄wtuonline的时候为了区分用户是来自手机版浏览器还是pc,针对不同平台选择不同的网站版本,最终总结如下:         ...

  5. 浅析PC机串口通讯流控制

    转自浅析PC机串口通讯流控制 我们在串行通讯处理中,常常看到RTS/CTS和XON/XOFF这两个选项,这就是两个流控制的选项,目前流控制主要应用于调制解调器的数据通讯中,但对普通RS232编程,了解 ...

  6. 开发板-PC机(宿主机)-虚拟机(VM)之间网络通信设置方法及须要注意的问题

    1.不使用路由器交换机 硬件连接: 使用网线将开发板和PC机相连 串口线将PC机和开发板相连 使用命令: ifconfig -a 串口控制端查看开发板的网络配置 route -n 串口控制端查看开发板 ...

  7. pc机进入android的shell

    一直都知道自己非常死板,刚刚再一次验证了.. 下载下来android开发必备的工具之后,就按部就班的一步步的来了.没想过这些工具有没有其它用处,更有甚者,在刚開始接触android的时候.居然不知道自 ...

  8. 【转】在嵌入式Linux和PC机Linux下使用popen函数时,程序运行结果有差异。

    下面程序演示了在嵌入式Linux和PC机Linux下使用popen函数时,程序的运行结果是有差异的. 两个程序 atest.c 和 btest.c,atest 检查是否有 btest 进程运行,如果没 ...

  9. 基于C/S模式的android手机与PC机通信系统的开发

    原文链接: http://blog.csdn.net/nupt123456789/article/details/8213486 基于C/S模式的android手机与PC机通信系统的开发 作者:郑海波 ...

随机推荐

  1. Dart语言入门(一)

    Dart 语言介绍 Dart 是谷歌在 2011 年推出的编程语言,是一种结构化 Web 编程语言,允许用户通过 Chromium 中所整合的虚拟机(Dart VM)直接运行 Dart 语言编写的程序 ...

  2. 从零学习Fluter(八):Flutter的四种运行模式--Debug、Release、Profile和test以及命名规范

    从零学习Fluter(八):Flutter的四种运行模式--Debug.Release.Profile和test以及命名规范 好几天没有跟新我的这个系列文章,一是因为这两天我又在之前的基础上,重新认识 ...

  3. 谈下git的基本操作

    在工作之后,我比较经常地接触git,关于git的用法,网上有很多的教程,而且git的指令是非常多的,强如阮一峰这样的高手也直言无法记住git的很多指令.实际上我也看了不少关于git指令的文章,个人觉得 ...

  4. quartz定时任务cron表达式

    cron 表达式格式:秒 分 时 日 月 周 年(可选) 子表达式范围 字段名 字段解释 值范围 特殊字符 Seconds 秒 0~59 , - * / Minutes 分 0~59 , - * / ...

  5. netstat -an查看到大量的TIME_WAIT状态的解决办法

    netstat下time_wait状态的tcp连接: 1.这是一种处于连接完全关闭状态前的状态: 2.通常要等上4分钟(windows server)的时间才能完全关闭: 3.这种状态下的tcp连接占 ...

  6. Python编写的Linux邮件发送工具

    之前有用过Linux自带的mail工具来定时发送邮件,但是要装mailx还有配mail.rc,这还比较正常,关键是到了ubantu下这工具用起来真是操蛋,如果哪天其他的unix like操作系统也有需 ...

  7. Bootstrap table 行编辑导航

    /*开启表格编辑方向键导航 方向键(←): VK_LEFT (37) 方向键(↑): VK_UP (38) 方向键(→): VK_RIGHT (39) 方向键(↓): VK_DOWN (40) */ ...

  8. SQL Server数据库————模糊查询和聚合函数

    ***********模糊查询*********/ 关键字: like (!!!!字符串类型) in (,,)  匹配()内的某个具体值(括号里可以写多个值) between... and.. 在某两 ...

  9. 如何定位“Operating system error 32(failed to retrieve text for this error. Reason: 15105)”错误中被占用的文件

      之前在这篇"Operating system error 32(failed to retrieve text for this error. Reason: 15105)"博 ...

  10. 3星|《陈志武金融投资课》:金融改善社会,A股投资策略

    从历史上的金融说起,介绍金融的基本知识.理念.大事.重要人物.也有一些A股投资策略和A股政策点评. 引用了不少学术研究成果做证据.讲历史的部分,功力比专业历史学者稍逊,毕竟这不是作者的专业. 我读后认 ...