AGG 高质量图形Word文档下载推荐.docx
《AGG 高质量图形Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《AGG 高质量图形Word文档下载推荐.docx(90页珍藏版)》请在冰点文库上搜索。
![AGG 高质量图形Word文档下载推荐.docx](https://file1.bingdoc.com/fileroot1/2023-4/28/910a360a-51e3-40bb-8715-c69b19fc8ff1/910a360a-51e3-40bb-8715-c69b19fc8ff11.gif)
platform/agg_platform_support.h"
8#include"
agg_ellipse.h"
9#include"
agg_conv_contour.h"
10#include"
agg_conv_stroke.h"
11classthe_application:
publicagg:
:
platform_support
12{
13public:
14the_application(agg:
pix_format_eformat,boolflip_y):
15agg:
platform_support(format,flip_y)
16{
17}
18virtualvoidon_draw()
19{
20//RenderingBuffer
21agg:
rendering_buffer&
rbuf=rbuf_window();
22agg:
pixfmt_bgr24pixf(rbuf);
23
24//Renderers
25typedefagg:
renderer_base<
agg:
pixfmt_bgr24>
renderer_base_type;
26renderer_base_typerenb(pixf);
27typedefagg:
renderer_scanline_aa_solid<
renderer_base_type>
renderer_scanline_type;
28renderer_scanline_typerensl(renb);
29
30//VertexSource
31agg:
ellipseell(100,100,50,50);
32
33//Coordinateconversionpipeline
34typedefagg:
conv_contour<
ellipse>
ell_cc_type;
35ell_cc_typeccell(ell);
36
37typedefagg:
conv_stroke<
ell_cc_type>
ell_cc_cs_type;
38ell_cc_cs_typecsccell(ccell);
39
40//ScanlineRasterizer
41agg:
rasterizer_scanline_aa<
>
ras;
42agg:
scanline_u8sl;
43
44//Draw
45renb.clear(agg:
rgba8(255,255,255));
46for(inti=0;
i<
5;
i++)
47{
48ccell.width(i*20);
49ras.add_path(csccell);
50rensl.color(agg:
rgba8(0,0,i*50));
51agg:
render_scanlines(ras,sl,rensl);
52}
53}
54};
55intagg_main(intargc,char*argv[])
56{
57the_applicationapp(agg:
pix_format_bgr24,false);
58app.caption("
AGGExample.Anti-AliasingDemo"
);
59if(app.init(600,400,agg:
window_resize))
60{
61returnapp.run();
62}
63return-1;
64}
编译这段代码的方法是(以VC为例):
1新建空白GUI项目(就是有WinMain的项目)
2把[AGG]\src里所有*.cpp加入到项目中
3把[AGG]\src\platform\Win32\*.cpp加入到项目中
4Ctrl+C/Ctrl+V上面的代码
5编译!
显示效果:
我们先不管agg_main及agg:
platform_support的问题,实际上agg:
platform_support只是AGG给我们方便显示AGG图形用的,真正应用时几乎不会用到(后面会讲到怎样把AGG图形画到HDC上)。
现在我们只需要知道这个框架可以生成一个窗体,当窗体重画时会调用virtualvoidon_draw()就行了。
现在直接从on_draw()开始看
6通过rbuf_window()方法得到一个agg:
rendering_buffer,它就是“RenderingBuffer”,是一块用于存放图像的内存块。
通过pixfmt_bgr24包装,我们就可以以像素为单位存取图像。
7agg:
renderer_base和agg:
renderer_scanline_aa_solid都属于"
渲染器Renderer"
。
renderer_base为底层渲染器,它支撑起所有的高层渲染器。
这里的renderer_scanline_aa_solid就是一个高层渲染器。
8agg:
ellipse是“顶点源VertexSource”,这个顶点源呈现的是一个圆形。
9agg:
conv_contour和agg:
conv_stroke作为“坐标转换管道Coordinateconversionpipeline”,conv_contour扩展轮廓线,conv_stroke只显示轮廓线(如果没有conv_stroke就会显示实心圆,可以去掉试试)。
10agg:
就是“ScanlineRasterizer”啦。
11agg:
render_scanlines函数执行这个AGG工作流程。
下面,我们来考察AGG显示流程中的每个环节。
理解每个环节最好的方法是编写实验代码,建议先参照这里建立一个可以运行的AGG实验环境。
顶点源(VertexSource)
顶点源是一种可以产生多边形所需要的“带命令的顶点”的对象。
比如三角形顶点源,就应该会产生一个带“MoveTo”命令的点,另外二个带"
命令的点和最终闭合的“ClosePoly”命令。
头文件
#include<
agg_path_storage.h>
//path_storage
agg_ellipse.h>
//ellipse
agg_arc.h>
//arc
agg_arrowhead.h>
//arrowhead
agg_curves.h>
//curve3,curve4
agg_gsv_text.h>
//gsv_text,gsv_text_outline
agg_rounded_rect.h>
//rounded_rect
...
类型
自定义类
所有实现了voidrewind(unsignedpath_id);
和unsignedvertex(double*x,double*y);
的类。
ellipse
圆,输入为中心点坐标和XY轴半径,本文所用的例子就使用了这个顶点源
arc
弧线,输入为中心点坐标和XY轴半径,以及起始和终止角(rad),顺时针/逆时针方向
curve3
贝塞尔曲线,输入为起点坐标、第一控制点坐标、终点点坐标
curve4
贝塞尔曲线,输入为起点坐标、第一控制点坐标、第二控制点坐标、终点坐标
gsv_text
使用AGG自带字模的文字输出(只支持ASCII码),使用start_point方法指定文字位置,text方法指定文字,flip指定是否上下倒转,size指定文字大小,适合与conv_stroke或gsv_text_outline配合。
gsv_text_outline<
可变换文字,输入为gsv_text和变换矩阵(默认为trans_affine,后文会提到)。
width方法设置文字宽度
rounded_rect
圆角方形,输入为左上角右下角坐标和圆角半径
path_storage
路径存储器,可以用join_path方法加入多个顶点源。
而且path_storage本身支持move_to,line_to,curve和arc_to等画线功能
arrowhead
箭头,它是作为标记点来用的
其中的arrowhead颇为特殊,它一般作为线段的标记点,具体用法是这样的:
arrowheadah;
ah.head(d1,d2,d3,d4);
//定义箭头
ah.tail(d1,d2,d3,d4);
//定义箭尾
VertexSourceVS;
//其它顶点源
//使用顶点转换器,并指定Markers类型为vcgen_markers_term
//顶点转换器可以是conv_dash、conv_stroke或conv_marker_adaptor,见后文《坐标转换管道》
//vcgen_markers_term:
以端点作为标记点
VertexSource,vcgen_markers_term>
csVS(VS);
...draw_term
//用conv_marker指定ah作为线段marker点的标记
conv_marker<
vcgen_markers_term,arrowhead>
arrow(csVS.markers(),ah);
ras.add_path(csVS);
ras.add_path(arrow);
//marker要紧随其后加入
...render
ah.head()和ah.tail()方法中的d1,d2,d3,d4参数的意义见下图
例,画一条简单的箭头直线(基于此处代码)
在on_draw()方法最后加上下列代码:
1agg:
2ah.head(0,10,5,5);
3ah.tail(10,10,5,5);
4//用path_storage生成一条直线
5agg:
path_storageps;
6ps.move_to(160,60);
7ps.line_to(100,100);
8//转换
9agg:
path_storage,agg:
vcgen_markers_term>
csps(ps);
10agg:
vcgen_markers_term,agg:
arrowhead>
11arrow(csps.markers(),ah);
12//画线
13ras.add_path(csps);
14agg:
render_scanlines_aa_solid(ras,sl,renb,agg:
rgba8(0,0,0));
15//画箭头
16ras.add_path(arrow);
17agg:
rgba8(255,0,0));
得到的图形是:
注意要加头文件:
#include"
agg_conv_marker.h"
agg_arrowhead.h"
agg_path_storage.h"
agg_vcgen_markers_term.h"
试验代码,自定义一个顶点源(基于此处代码)
为了对顶点源有更深入的了解,我们要自己实现一个顶点源,这个顶点源只是很简单的一个三角形。
前面说过,只要实现了voidrewind(unsignedpath_id);
和unsignedvertex(double*x,double*y);
方法就可以作为顶点源。
rewind方法指示顶点源回到第一个顶点;
vertex方法取出当前顶点然后把当前顶点下移,返回值是当前顶点所带的命令。
所谓的命令是一个enumpath_commands_e类型,定义如下:
18enumpath_commands_e
19{
20path_cmd_stop=0,//----path_cmd_stop
21path_cmd_move_to=1,//----path_cmd_move_to
22path_cmd_line_to=2,//----path_cmd_line_to
23path_cmd_curve3=3,//----path_cmd_curve3
24path_cmd_curve4=4,//----path_cmd_curve4
25path_cmd_curveN=5,//----path_cmd_curveN
26path_cmd_catrom=6,//----path_cmd_catrom
27path_cmd_ubspline=7,//----path_cmd_ubspline
28path_cmd_end_poly=0x0F,//----path_cmd_end_poly
29path_cmd_mask=0x0F//----path_cmd_mask
30};
path_commands_e还能和path_flags_e组合:
31enumpath_flags_e
32{
33path_flags_none=0,//----path_flags_none
34path_flags_ccw=0x10,//----path_flags_ccw
35path_flags_cw=0x20,//----path_flags_cw
36path_flags_close=0x40,//----path_flags_close
37path_flags_mask=0xF0//----path_flags_mask
38};
vertex()返回的命令中含有path_cmd_stop时表示结束。
39//等边三角形
40classtriangle{
41public:
42triangle(doublecx,doublecy,doubler)//中心点,r为中心点到边的长度
43{
44//直接准备好三个点
45m_step=0;
46m_pt[0].x=cx;
m_pt[0].y=cy-r;
47m_pt[1].x=cx+r*0.866;
m_pt[1].y=cy+r*0.5;
48m_pt[2].x=cx-r*0.866;
m_pt[2].y=cy+r*0.5;
49//AGG把方向作为区分多边形内部和外部的依据,可以试试m_pt[1]和m_pt[2]对调
50}
51voidrewind(unsigned)
52{
53m_step=0;
54}
55unsignedvertex(double*x,double*y)
56{
57switch(m_step++)
58{
59case0:
60//第一步,move_to
61*x=m_pt[0].x;
62*y=m_pt[0].y;
63returnagg:
path_cmd_move_to;
64case1:
65case2:
66//第二、三步,line_to
67*x=m_pt[m_step-1].x;
68*y=m_pt[m_step-1].y;
69returnagg:
path_cmd_line_to;
70case3:
71//第四步,闭合多边形
72returnagg:
path_cmd_end_poly|agg:
path_flags_close;
73default:
74//第五步,结束
75returnagg:
path_cmd_stop;
76}
77}
78private:
79agg:
point_dm_pt[3];
80unsignedm_step;
81};
在on_draw()方法里把
agg:
改成triangleell(100,100,50);
typedefagg:
改成typedefagg:
triangle>
除了文字输出功能(gsv_text只能输出ASCII文字),上面这些顶点源提供的图形丰富程度已经超过了系统API。
文字输出功能将以单独的篇幅讲述。
Coordinateconversionpipeline坐标转换管道
坐标转换管道用于改变顶点源产生的顶点,包括坐标、命令、产生新顶点等。
如对顶点进行矩阵变换、插入顶点形成虚线之类的功能。
变换矩阵(trans_affine)
在认识转换管道之前,先了解一下AGG的变换矩阵。
通过顶点坐标与矩阵的运行,我们可以得到新的坐标。
关于图像的矩阵运算,MSDN里有一篇关于GDI+矩阵运算的文章,很值得一看
#include<
agg_trans_affine.h>
trans_affine
成员变量
doublesx,shy,shx,sy,tx,ty;
这六个变量组成一个2*3的矩阵,与坐标计算后得到一个新的坐标。
比如对点(x,y)进行变换,则新的点(x'
y'
)为:
x'
=x*sx+y*shx+tx;
y'
=x*shy+y*sy+ty;
成员方法
voidtransform(double*x,double*y)const;
用上面的公式转换x,y坐标
consttrans_affine&
scale(doubles);
scale(doublex,doubley);
缩放
rotate(doublea);
旋转,弧度单位(pi/180)
translate(doublex,doubley)
平移
trans_affineoperator*(consttrans_affine&
m);
矩阵乘法
invert();
取反矩阵
坐标转换管道中有个叫conv_transform的转换器,它能利用矩阵对源顶点进行变换,我们先在这里玩玩吧^_^
实验代码(基于此处代码)
加入头文件#include"
agg_conv_transform.h"
把on_draw()方法的里从“//VertexSource”到“//ScanlineRasterizer”之间的代码改写成:
1//VertexSource
2agg:
ellipseell(0,0,50,50);
//圆心在中间
3
4//Coordinateconversionpipeline
5agg:
trans_affinemtx;
6mtx.scale(0.5,1);
//x轴缩小到原来的一半
7mtx.rotate(agg:
deg2rad(30));
//旋转30度
8mtx.translate(100,100);
//平移100,100
9typedefagg:
conv_transform<
ell_ct_type;
10ell_ct_typectell(ell,mtx);
//矩阵变换
11