📄 tutorial_43.htm
字号:
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">现在我们已经能创建基于FreeType的程序了,但我们还不能运行它,因为我们需要freetype-6.dll文件。
<p>好了,现在我们可以开始编写我们的程序了,我们从13课的代码开始,我们添加两个新的文件"freetype.cpp"和"freetype.h"。我们把和FreeType相关的内容放在这两个文件里。</p>
<p>好了,让我们从freetype.h开始吧。</p>
<p>按惯例我们包含一些需要的头文件</p>
</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre>#ifndef FREE_NEHE_H<br>#define FREE_NEHE_H</pre>
<p><span class="theme">//FreeType 头文件</span><br>
#include <ft2build.h><br>
#include <freetype/freetype.h><br>
#include <freetype/ftglyph.h><br>
#include <freetype/ftoutln.h><br>
#include <freetype/fttrigon.h></p>
<p><span class="theme">//OpenGL 头文件</span><br>
#include <windows.h> <br>
#include <GL/gl.h><br>
#include <GL/glu.h></p>
<p><span class="theme">//STL 头文件</span><br>
#include <vector><br>
#include <string></p>
<p><span class="theme">//STL异常类</span><br>
#include <stdexcept><br>
#pragma warning(disable: 4786)</p>
<p></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">我们将把每个字符需要的信息封装在一个结构中,这样就像使用WGL字体一样,我们可以分别控制每个字符的显示状态。</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre><span class="theme">// 把所有的操作放在名字空间freetype中,这样可以避免与其他函数的冲突</span><br>namespace freetype
{</pre>
<p><span class="theme">// 使用vector和string名字空间</span><br>
using std::vector;<br>
using std::string;</p>
<p><span class="theme">// 这个结构保存字体信息 </span><br>
struct font_data <br>
{<br>
float h; <span class="theme">// 字体的高度</span><br>
GLuint * textures; <span class="theme">// 使用的纹理 </span><br>
GLuint list_base; <span class="theme">// 显示列表的值</span></p>
<p> <span class="theme">// 初始化结构</span><br>
void init(const char * fname, unsigned int h);</p>
<p> <span class="theme">// 清楚所有的资源</span><br>
void clean();<br>
};</p>
<p></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">最后一件事是定义我们输出字符串的原形:</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre><span class="theme">// 把字符输出到屏幕</span><br>void print(const font_data &ft_font, float x, float y, const char *fmt, ...);</pre>
<p>} </p>
<p>#endif</p>
<p></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">上面就是FreeType的头文件,下面我们看看怎样实现它</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre>#include "freetype.h"</pre>
<p>namespace freetype {</p>
<p></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">我们使用纹理去显示字符,在OpenGL中纹理大小必须为2的次方,这个函数用来字符的大小近似到这个值。所以我们有了如下的方程:</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre><span class="theme">// 这个函数返回比a大的,并且是最接近a的2的次方的数</span><br>inline int next_p2 (int a )<br>{<br> int rval=1;<br> // rval<<=1 Is A Prettier Way Of Writing rval*=2; <br> while(rval<a) rval<<=1;<br> return rval;<br>}</pre>
<p></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">下面一个函数为make_dlist, 它是这个代码的核心。它包含FT_Face对象,它是FreeType用来保存字体信息的类,接着创建一个显示列表。</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre><span class="theme">// 为给定的字符创建一个显示列表</span><br>void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) {</pre>
<p> <span class="theme">// 载入给定字符的轮廓</span><br>
if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT ))<br>
throw std::runtime_error("FT_Load_Glyph failed");</p>
<p> <span class="theme">// 保存轮廓对象</span><br>
FT_Glyph glyph;<br>
if(FT_Get_Glyph( face->glyph, &glyph ))<br>
throw std::runtime_error("FT_Get_Glyph failed");</p>
<p> <span class="theme">// 把轮廓转化为位图</span><br>
FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );<br>
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;</p>
<p> <span class="theme">// 保存位图</span><br>
FT_Bitmap& bitmap=bitmap_glyph->bitmap;</p>
<pre>}
</pre>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="tl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="tc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="100%"></td>
<td class="tr"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="l"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="back3" valign="top" width="100%">现在我们已经从FreeType中获得了位图,我们需要把它转化为一个满足OpenGL纹理要求的位图。你必须知道,在OpenGL中位图表示黑白的数据,而在FreeType中我们使用8位的颜色表示位图,所以FreeType的位图可以保存亮度信息。</td>
<td class="r"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td class="bl"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="bc" width="100%"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td>
<td class="br"><img alt="" src="Tutorial_43_files/blank1.gif" height="28" width="28"></td></tr></tbody></table>
<pre><span class="theme">// 转化为OpenGl可以使用的大小</span><br> int width = next_p2( bitmap.width );<br> int height = next_p2( bitmap.rows );</pre>
<p> <span class="theme">// 保存位图数据</span><br>
GLubyte* expanded_data = new GLubyte[ 2 * width * height];</p>
<p> <span class="theme">// 这里我们使用8位表示亮度8位表示alpha值</span><br>
for(int j=0; j <height;j++) {<br>
for(int i=0; i < width; i++){<br>
expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] = <br>
(i>=bitmap.width || j>=bitmap.rows) ?<br>
0 : bitmap.buffer[i + bitmap.width*j];<br>
}<br>
}</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -