使用FreeType在电脑端显示(字母或者汉子)

============================================================================================
一、FreeType使用详解		
参考来源:
1、freetype-doc-2.10.1.tar/freetype-doc-2.10.1/freetype-2.10.1/docs/tutorial/step1.html(文字说明)
2、freetype-2.10.1.tar/freetype-2.10.1/docs/reference/site/ft2-base_interface.html(函数定义)
3、韦东山视频:freetype介绍。
4、项目1数目相框_笔记\04\freetype-doc-2.10.1.tar\freetype-doc-2.10.1\freetype-2.10.1\docs\tutorial\example1.c(freetype-2.10.1工程自带的C代码)。


技巧:如果想更好地理解代码每个函数的定义,可以在source insight添加freetype-2.10.1.tar工程,	结合对应文档进行理解
============================================================================================
I. Simple Glyph Loading(简单字形加载)
	1. Header Files(头文件)
		Include the file named ft2build.h.(包含头文件 )
		
		#include <ft2build.h>
		#include FT_FREETYPE_H
		
	2. Library Initialization(库初始化)
		
		To initialize the FreeType library, create a variable of type FT_Library named, for example, library, and call the function FT_Init_FreeType.
		用法:为了初始化FreeType library。需要的创建一个FT_Library类型的变量,比如library。然后调用函数FT_Init_FreeType。
		FT_Init_FreeType的用法:{FT_Init_FreeType( &library );}返回值:0表示成功。返回错误码见fterrdef.h.
	3. Loading a Font Face(用三种方式,1、从一个字库文件创建Face对象;2、从From Memory创建一个Face对象;3、其他方式)
		a. From a Font File(通过调用FT_New_Face打开一个字库文件从而创建一个新的face(这个可以理解为一个平面)对象,其代表一个字体文件。)调用函数FT_New_Face{FT_New_Face( library,
                     "/usr/share/fonts/truetype/arial.ttf",
                     0,
                     &face )}参数1:FT_Library类型的变量;参数2:字库文件路径();参数3:经常使用0;参数4:为一指针,用来描述face这一个对象。返回值:成功为0.其他看对应文档
			要知道给定字体文件包含多少个面,可以将第三参数设置为-1,然后检查face->num_faces的值,该值指示字体文件中嵌入了多少个面。 
		b. From Memory(不常使用)  
			调用函数FT_New_Memory_Face( library,
                            buffer,    /* first byte in memory */
                            size,      /* size in bytes        */
                            0,         /* face_index           */
                            &face );
	4. Accessing the Face Data(访问Face对象中数据)
		可以使用的face−>num_glyphs等等一些成员.方式访问其中的数据。
	5. Setting the Current Pixel Size(设置当前像素大小,即填充生成Face)
		a、使用到的函数(设置一个字符宽和高各多少像素点)定义:  
				FT_Set_Char_Size( FT_Face     face,
									FT_F26Dot6  char_width,
									FT_F26Dot6  char_height,
									FT_UInt     horz_resolution,
									FT_UInt     vert_resolution );
		参数1:	之前得到的Face;参数2:字符的高度:参数3:字符宽度;参数4:水平方向分辨率;参数5:竖直方向分辨率
		参数23如何设置:
			 The character widths and heights are specified in 1/64th of points,A point is a physical distance, equaling 1/72th of an inch。也就是说字符高度和宽度的单位是的1/64*1/72英寸。如果第二个参数的值是0,则表明宽度和高度相等。
		参数45如何设置:
			The horizontal and vertical device resolutions are expressed in dots-per-inch, or dpi。也就是说每英寸里面存在多少像素。如果第二个参数0,则表明水平和竖直相等。 If both values are zero, 72 dpi is used for both dimensions.如果都为0,表明都使用72dpi。
		如何计算一个字符里面包含多少个像素点呢:
			举例说明:
			char_width= 100
			char_height= 100
			horz_resolution= 200
			vert_resolution= 200
			计算一个字符宽度由几个像素组成:100*1/64*1/72*200=4.3像素:同理计算字符高度需要多少像素。
		b、如果我们不想使用FT_Set_Char_Size,我们可以使用FT_Set_Pixel_Sizes
			函数定义:  FT_Set_Pixel_Sizes( FT_Face  face,
											FT_UInt  pixel_width,
											FT_UInt  pixel_height );
		因为使用FT_Set_Char_Size最终是得到了一个字符需要多少个像素组成,而对于使用FT_Set_Pixel_Sizes我们可以直接使用这个函数设置pixel_width和pixel_height。
	6. Loading a Glyph Image
		a. Converting a Character Code Into a Glyph Index
			知识点:
			如果我们想要得到一个字符的glyph(关键信息),我们就需要提供这个字符的(唯一的)字符码(ascii、unicode、GBK等等。)。每一个字库文件中都存在一个charmap表。我可以通过这个表把提供字符码(可能是ascii也有点可能是unicode)作为索引在字库文件中找到该字符对应的glyph。
			
			使用的函数:  FT_Get_Char_Index( FT_Face   face,
											FT_ULong  charcode );
		b. Loading a Glyph From the Face
			说明:			  
			1、加载找到的The glyph image到 face->glyph插槽中即slot中;
			The glyph image is always stored in a special object called a glyph slot,Each face object has a single glyph slot object that can be accessed as face->glyph.每一个Face都有一个slot object,slot object用来的存储The glyph image
			
			Loading a glyph image into the slot is performed by calling FT_Load_Glyph.加载一个a glyph image到这个插槽对象中,用法如下:
			函数:FT_Load_Glyph( FT_Face   face,
										FT_UInt   glyph_index,
										FT_Int32  load_flags );
										
			2、将slot(face->glyph)中The glyph image转化为位图(真正的图像,也就是字符点阵)
			The field face−>glyph−>format describes the format used for storing the glyph image in the slot. If it is not FT_GLYPH_FORMAT_BITMAP, one can immediately convert it to a bitmap through FT_Render_Glyph.
			说明:如果face−>glyph−>format里面图像格式不是FT_GLYPH_FORMAT_BITMAP,那就立即将slot(face->glyph)中的图像立即的转化为a bitmap(位图),需要使用的函数:
										FT_Render_Glyph( FT_GlyphSlot    slot,
													FT_Render_Mode  render_mode );
			参数1:face->glyph变量。
			参数2:位图的呈现模式
		c. Using Other Charmaps
			在6.a步骤中,如果我们不想使用face中charmap表格默认的索引(unicode),我们提供可能是其他编码,我们可以通过相应的函数修该对应的charmaps
				函数:error = FT_Select_Charmap(
													face,               /* target face object */
													FT_ENCODING_BIG5 ); /* encoding
				参数2含义:指定使用编码,这里是FT_ENCODING_BIG5
				
				那么如何确定已经打开的字库文件中包含多少charmaps,可以用以下代码:
				for ( n = 0; n < face->num_charmaps; n++ )
						{
							charmap = face->charmaps[n];
							if ( charmap->platform_id == my_platform_id &&
									charmap->encoding_id == my_encoding_id )
						{
					found = charmap;
					break;
					}

		d. Glyph Transformations
			如果的我们需要将显示字符做一个平移或者旋转,就需要使用一个函数:
			  FT_Set_Transform( FT_Face     face,
								FT_Matrix*  matrix,
								FT_Vector*  delta );
			参数介绍:
			参数2:指向一个matrix的指针,首先定义一个FT_Matrix的变量。对该变量进行初始化(旋转多少度。)。
			参数3:这个字符基点(原点)在定义的显示区域的位置。
			  设置参数3有一个知识点:
               字库文件中的字符基点(原点)使用的是笛卡尔坐标(位于左下角)。而对于LCD而言话,其坐标原点位于屏幕的左上角,因此设置FT_Vector类型变量时。需要将字符位置进行一个转换。矢量坐标表示为1/64个像素(也称为26.6个定点数,因此需要乘以一个64)。
	7. Simple Text Rendering
		The idea is to create a loop that loads one glyph image on each iteration, converts it to a pixmap, draws it on the target surface, then increments the current pen position.(其思想是创建一个循环,在每次迭代中加载一个字形图像,将其转换为像素图,在目标表面绘制它,然后增加当前笔的位置。)
		========================================================================================================
		a. Basic Code(基本的代码)
		========================================================================================================
					... initialize library ...
					... create face object ...
					... set character size ...

					pen_x = 300;                 //字符显示的位置
					pen_y = 200;
					
					
					for ( n = 0; n < num_chars; n++ ) //使用一个循环遍历整个所要显示的字符
					{
					  FT_UInt  glyph_index;                                


					  /* retrieve glyph index from character code */
					  glyph_index = FT_Get_Char_Index( face, text[n] );    //循环内step1 寻找第n个字符对应的index

					  /* load glyph image into the slot (erase previous one):将的生成的image放进slot */
					  error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );  //循环内step2,根据index找到其对应的字形轮廓
					  if ( error )
						continue;  /* ignore errors */

					  /* convert to an anti-aliased bitmap:转化为位图(位图是点阵吗?) */
					  error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );  //循环内step3,将字形轮廓转化为位图
					  if ( error )
						continue;

					  /* now, draw to our target surface */    						//循环内step4
					  my_draw_bitmap( &slot->bitmap,
									  pen_x + slot->bitmap_left,
									  pen_y - slot->bitmap_top );
					  /* increment pen position */
					  pen_x += slot->advance.x >> 6;								//循环内step5
					  pen_y += slot->advance.y >> 6; /* not useful for now */
					}
					总结:
					这一快代码是循环体内最基本代码,目前我的疑惑:
					my_draw_bitmap函数如何实现(看了源码现在也不太懂(目前不知道slot->bitmap放的是什么,点阵?,那应该是一堆的01。但是结合后面调用的show image函数中的{putchar( image[i][j] == 0 ? ' '
                                : image[i][j] < 128 ? '+'
                                                    : '*' );},又好像不对 。现在无法解决。))
		=======================================================================================================
		b.Refined code(精简的代码)建议使用为什么有这一部分b呢(主要是与a进行对比,不同在for循环体内)
		========================================================================================================
					for ( n = 0; n < num_chars; n++ )
						{
						  /* load glyph image into the slot (erase previous one) */
						  error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );   //step1
						  if ( error )
							continue;  /* ignore errors */

						  /* now, draw to our target surface */
						  my_draw_bitmap( &slot->bitmap,
										  pen_x + slot->bitmap_left,
										  pen_y - slot->bitmap_top );

						  /* increment pen position */
						  pen_x += slot->advance.x >> 6;
						}
	总结:对比a. Basic Code(基本的代码)和bRefined code(精简的代码)
				a中循环内step1~step3被b中step1替代同样可以达到效果(将得到的glyph转化为位图)
	============================================================================================
二、使用韦老师提供的freetype-2.4.10源码进行编译安装 freetype,然后运行韦老师的代码
============================================================================================
因为编写的代码代码需要调用的安装freetype所生成的库文件(包括头文件,函数的定义等等)。
自己的体会:
1、如何安装freetype。可从源码根目录中READM出发,查看安装的过程。
2、安装freetype之后,就会在/user/local(默认)下面的目录(环境变量)中生成库文件。安装文档中也有讲。
3、下面就是执行韦老师的程序了
gcc -o example1 example1.c
出错信息:/usr/local/include/ft2build.h:56:38: fatal error: freetype/config/ftheader.h: No such file or directory
但是经过查看/usr/local/include/ft2build.h中56行 #include <freetype/config/ftheader.h>。在进行查看发现/usr/local/include/freetype2/freetype/config/ftheader.h存在头文件。这表示程序未找到对应路径因此需要指定路径:gcc -o example1 example1.c -I /usr/local/include/freetype2/。也就是说在freetype2/然后执行#include <freetype/config/ftheader.h>。执行发现

example1.c:(.text+0x25b): undefined reference to `FT_Init_FreeType'
example1.c:(.text+0x284): undefined reference to `FT_New_Face'
example1.c:(.text+0x29d): undefined reference to `FT_Set_Pixel_Sizes'
example1.c:(.text+0x2c4): undefined reference to `cos'
example1.c:(.text+0x2f5): undefined reference to `sin'
example1.c:(.text+0x332): undefined reference to `sin'
example1.c:(.text+0x363): undefined reference to `cos'
example1.c:(.text+0x3b6): undefined reference to `FT_Set_Transform'
example1.c:(.text+0x3de): undefined reference to `FT_Load_Char'
example1.c:(.text+0x465): undefined reference to `FT_Done_Face'
example1.c:(.text+0x471): undefined reference to `FT_Done_FreeType'
提示是未定义,但是,我们已经包含了对应的头文件,因此程序链接的时候未找到安装freetype生成的库文件,因此的需要指定生成的库文件(注意:去掉lib前缀):
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype   执行发现:
example1.c:(.text+0x2c4): undefined reference to `cos'
example1.c:(.text+0x2f5): undefined reference to `sin'
example1.c:(.text+0x332): undefined reference to `sin'
example1.c:(.text+0x363): undefined reference to `cos'
表明链接的时候未找到对应的数学库,因此执行(不能加-lmath而是加-lm):
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm                成功
然后执行./example1 BROADW.TTF abc.
执行成功
============================================================================================
三、使用韦老师提供的freetype-2.4.10源码进行编译安装 freetype,然后运行自己写的代码
============================================================================================
自己写的代码,是可以运行出结果,只能显示单个字符,如果是多个字符的话,就会导致,字符存在重合,我的代码里面已经使用
		pen.x += slot->advance.x;
		pen.y += slot->advance.y;
		者这句代码,但是实验的结果,表明第二字符之后origin(原点仍然没用移动),后面解决这个问题。			
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值