方式二、使用字体引擎(Font Engine)
AGG的字体引擎利用WinAPI:GetGlyphOutline或FreeType库得到字体数据(字模),它可以处于 “Scanline Rasterizer”层或“顶点源”层。要使用字体引擎,要把相应的字体引擎源码(agg_font_win32_tt.cpp或 agg_font_freetype.cpp)加入项目一起编译。
头文件
- #include <agg_font_win32_tt.h>
- #include <agg_font_freetype.h>
注意,它们都有自己的文件夹,不是在agg的include文件夹里。
类型
agg::font_engine_win32_tt_int16
agg::font_engine_win32_tt_int32
agg::font_engine_freetype_int16
agg::font_engine_freetype_int32
显然,前两个利用WinAPI实现,后两个利用FreeType库实现。类型后面的_int16或_int32后缀用于指定坐标单位, 一般int16已经可以满足要求。
成员类型定义:
typedef path_adaptor_type |
把字体数据包装成顶点源的类 |
typedef gray8_adaptor_type |
把字体数据包装成Scanline Rasterizer的类 |
typedef mono_adaptor_type |
把字体数据包装成Scanline Rasterizer的类,但无AA效果 |
成员属性:
double: height |
字体高度,单位为Point(和Word里的单位一样) |
double: width |
字体宽度,单位为Point*2.4。0表示规则大小(height/2.4) |
bool: italic |
斜体 |
bool: flip_y |
上下翻转 |
bool: hinting |
字体修正 |
unsigned: resolution |
字体解析度,单位为dpi |
成员方法:
void transform(const trans_affine& affine); |
按矩阵变换 |
bool create_font(const char* typeface_, glyph_rendering ren_type); |
font_engine_win32_tt_*专有方法 建立字体,typeface_为字体名,ren_type稍后再说 |
bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, const char* font_mem = 0, const long font_mem_size = 0); |
font_engine_freetype_*专有方法 建立字体,font_name是字体文件名或字体名 |
bool prepare_glyph(unsigned glyph_code) unsigned data_size() const void write_glyph_to(int8u* data) const |
得到字体数据(字模)所需方法 |
字体引擎的create_font()方法和load_font()方法需要一个glyph_rendering类型的ren_type参数,它决定了字 体数据的形式。三个成员类型定义:path_adaptor_type、gray8_adaptor_type和mono_adaptor_type所包 装的字体数据是 不一样的,只有与ren_type参数对应才能生成正确的AGG显示节点。
glyph_rendering是一个枚举类型,定义是:
- enum agg::glyph_rendering{
- glyph_ren_native_mono,
- glyph_ren_native_gray8,
- glyph_ren_outline,
- glyph_ren_agg_mono,
- glyph_ren_agg_gray8
- };
示例代码1 - 从顶点源层输出文字
- typedef agg::font_engine_win32_tt_int16 fe_type;
- typedef fe_type::path_adaptor_type vs_type;
-
- fe_type fe( ::GetDC(::GetActiveWindow()) );
- fe.height(36.0);
- fe.flip_y(true);
- fe.hinting(true);
-
- fe.create_font("黑体",agg::glyph_ren_outline);
-
- wchar_t *s = L"C++编程";
-
- std::vector<agg::int8u> data;
-
- vs_type vs;
-
- agg::conv_curve<vs_type> ccvs(vs);
-
- int x=20,y=100;
- for(;*s;s++)
- {
-
- if(!fe.prepare_glyph(*s)) continue;
-
- data.resize( fe.data_size() );
- fe.write_glyph_to( &data[0] );
-
- vs.init(&data[0], data.size(), x, y);
-
- x += fe.advance_x();
- y += fe.advance_y();
-
- ras.add_path(ccvs);
- agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba(0,0,1));
- }
由于字体顶点源可能会包含带Curve命令的顶点,所以要用conv_curve来 转换。你可以试试去掉这层转换,字符'C' 就不会那么平滑了。
示例代码2 - 从Scanline Rasterizer层输出文字
-
- typedef agg::font_engine_win32_tt_int16 fe_type;
- typedef fe_type::gray8_adaptor_type ras_type;
- typedef ras_type::embedded_scanline sl_type;
-
- fe_type fe( ::GetDC(::GetActiveWindow()) );
- fe.height(36.0);
- fe.flip_y(true);
- fe.hinting(true);
-
- fe.create_font("黑体",agg::glyph_ren_agg_gray8);
-
- wchar_t *s = L"C++编程";
-
- std::vector<agg::int8u> data;
-
- ras_type ras_font;
- sl_type sl_font;
-
- int x=20,y=100;
- for(;*s;s++)
- {
-
- if(!fe.prepare_glyph(*s)) continue;
-
- data.resize( fe.data_size() );
- fe.write_glyph_to( &data[0] );
-
- ras_font.init(&data[0], data.size(), x, y);
-
- x += fe.advance_x();
- y += fe.advance_y();
-
- agg::render_scanlines_aa_solid(ras_font,sl_font,renb,agg::rgba(0,0,1));
- }
显示效果