书接上文,昨天装了MinGW,主要原因之一是要用到MSYS,所以顺手把FFMPEG又编译了一遍。
回到主题,其实我是想编译矢量库,因为最近要学习一些计算几何算法,所以找个方便的2D画图库就很重要。
说白了其实是懒得用OpenGL写画几何体代码,画线,AA什么的。
不管怎么说,介绍看的是这篇文章。
http://www.cnblogs.com/yanhuiw/p/3885144.html
提到了3个矢量库,因为墙的原因,google的Skia死活弄不下来,所以只写前两个。
首先是AGG,http://www.antigrain.com/
第三方依懒库只有freetype,而freetype自带sln工程,所以编译没有问题,我直接打开的2010工程
freetype2\builds\windows\vc2010
然后新建一个Win32 Console Static library空工程,把AGG源码手动添加进工程,注意平台相关,别把没用的也加进去
并把相关目录加到include目录中,再加上freetype2的include,library,
编译就行了
相关目录
font_freetype
font_win32_tt
gpc
src
src\ctrl
src\platform\win32
========================================
然后新建一个Win32 Project,也就是窗口程序,实际上我建的Win32 Console空工程,然后在工程设置又改成的窗口,怎么弄都行。
配置上AGG的include,library目录
然后使用下面这个测试hello world,原文在哪忘了,只是测试下。
1 #include "agg_basics.h" 2 #include "agg_rendering_buffer.h" 3 #include "agg_rasterizer_scanline_aa.h" 4 #include "agg_scanline_u.h" 5 #include "agg_renderer_scanline.h" 6 #include "agg_pixfmt_rgb.h" 7 #include "platform/agg_platform_support.h" 8 #include "agg_ellipse.h" 9 #include "agg_conv_contour.h" 10 #include "agg_conv_stroke.h" 11 12 #include "agg_conv_marker.h" 13 #include "agg_arrowhead.h" 14 #include "agg_path_storage.h" 15 #include "agg_vcgen_markers_term.h" 16 17 18 #include <agg_conv_stroke.h> // conv_stroke 19 #include <agg_conv_dash.h> // conv_dash 20 #include <agg_conv_marker.h> // conv_marker 21 #include <agg_conv_curve.h> // conv_curve 22 #include <agg_conv_contour.h> // conv_contour 23 #include <agg_conv_smooth_poly1.h> // conv_smooth_poly1.h 24 #include <agg_conv_bspline.h> // conv_bspline 25 #include <agg_conv_transform.h> // conv_transform 26 27 28 class the_application : public agg::platform_support 29 { 30 public: 31 the_application(agg::pix_format_e format, bool flip_y) : 32 agg::platform_support(format, flip_y) 33 { 34 } 35 36 virtual void on_draw() 37 { 38 //Rendering Buffer //用于存放像素点阵数据的内存块,这里是最终形成的图像数据 39 agg::rendering_buffer &rbuf = rbuf_window(); 40 agg::pixfmt_bgr24 pixf(rbuf); 41 42 // Renderers 43 typedef agg::renderer_base<agg::pixfmt_bgr24> renderer_base_type; //底层渲染器 44 renderer_base_type renb(pixf); 45 46 // typedef agg::renderer_scanline_aa_solid<renderer_base_type> renderer_scanline_type; //高层渲染器 47 typedef agg::renderer_scanline_bin_solid<renderer_base_type> renderer_scanline_type; //高层渲染器 48 49 renderer_scanline_type rensl(renb); 50 /* 51 // Vertex Source 52 //agg::ellipse ell(100,100,50,50); //顶点源,里面存放了一堆2D顶点以及对应的命令,这个顶点源呈现的是一个圆形 53 agg::triangle ell(100,100,50); 54 55 // Coordinate conversion pipeline //坐标转换管道,它可以变换Vertex Source中的顶点,比如矩阵变换,轮廓提取,转换为虚线等。 56 //typedef agg::conv_contour<agg::ellipse> ell_cc_type; //扩展轮廓线 57 typedef agg::conv_contour<agg::triangle> ell_cc_type; 58 ell_cc_type ccell(ell); 59 60 typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type; //只显示轮廓线 61 ell_cc_cs_type csccell(ccell); 62 */ 63 64 // Vertex Source 65 66 agg::ellipse ell(0, 0, 50, 50); // 圆心在中间 67 // Coordinate conversion pipeline 68 agg::trans_affine mtx; // trans_affine不 仅仅用于源顶点的变换,在AGG库中有不少地方都能看到它 69 mtx.scale(0.5, 1); // x轴缩小到原来的一半 70 mtx.rotate(agg::deg2rad(30)); // 旋转30度 71 mtx.translate(100, 100); // 平移100,100 72 typedef agg::conv_transform<agg::ellipse> ell_ct_type; 73 ell_ct_type ctell(ell, mtx); // 矩阵变换 74 75 typedef agg::conv_contour<ell_ct_type> ell_cc_type; 76 ell_cc_type ccell(ctell); // 轮廓变换 77 78 typedef agg::conv_dash<ell_cc_type> ell_cd_type; 79 ell_cd_type cdccell(ccell); 80 cdccell.add_dash(5, 5); 81 82 83 typedef agg::conv_stroke<ell_cd_type> ell_cc_cs_type; 84 // ell_cc_cs_type csccell(ccell); // 转换成多义线 85 ell_cc_cs_type csccell(cdccell); 86 87 // csccell.width(3); 88 89 90 // Scanline Rasterizer //把顶点数据(矢量数据)转换成一组水平扫描线,扫描线由一组线段(Span)组成,线段(Span)包含了起始位置、长度和覆盖率(可以理解为透明度)信息。AGG的抗锯齿(Anti-Aliasing)功能也是在这时引入的。 91 agg::rasterizer_scanline_aa<> ras; 92 agg::scanline_u8 sl; 93 94 // Draw 95 renb.clear(agg::rgba8(255, 255, 255)); 96 // renb.clip_box(30,30,160,160); // 设置可写区域 97 98 for (int i = 0; i<5; i++) 99 { 100 ccell.width(i * 20); 101 ras.add_path(csccell); 102 rensl.color(agg::rgba8(0, 0, i * 50)); 103 // agg::render_scanlines(ras,sl,rensl); 104 agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(0, 0, i * 50)); 105 106 } 107 108 109 static double i = 0; 110 ++i; 111 agg::path_storage ps; 112 113 ps.start_new_path(); 114 ps.move_to(200+ i, 60); 115 ps.line_to(400, 100); 116 ps.line_to(300, 140); 117 ps.end_poly(); 118 119 120 121 agg::conv_stroke<agg::path_storage, agg::vcgen_markers_term> csps(ps); 122 ras.add_path(csps); 123 agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(0, 0, 0)); 124 125 126 127 128 129 /* 130 agg::arrowhead ah; 131 ah.head(0,10,5,5); 132 ah.tail(10,10,5,5); 133 // 用path_storage生成一条直线 134 agg::path_storage ps; 135 ps.move_to(160,60); 136 ps.line_to(100,100); 137 // 转换 138 agg::conv_stroke<agg::path_storage, agg::vcgen_markers_term> csps(ps); 139 agg::conv_marker<agg::vcgen_markers_term, agg::arrowhead> 140 arrow(csps.markers(), ah); 141 // 画线 142 ras.add_path(csps); 143 agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(0,0,0)); 144 // 画箭头 145 ras.add_path(arrow); 146 agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(255,0,0)); 147 148 149 agg::triangle t(100,100,50);//自定义顶点源 150 agg::conv_smooth_poly1_curve<agg::triangle> cspct(t); 151 ras.add_path(cspct); 152 agg::render_scanlines_aa_solid( 153 ras,sl,renb,agg::rgba8(255,0,0)); 154 155 156 for(int j=0; j<20; j++) 157 pixf.blend_vline(50+j,20,100,agg::rgba(j/20.0,0,0),128); 158 159 160 161 agg::int8u* p = rbuf.row_ptr(20);//得到第20行指针 162 memset(p,0,rbuf.stride_abs());//整行以0填充 163 */ 164 } 165 166 virtual void on_post_draw(void* raw_handler) override 167 { 168 } 169 170 }; 171 172 173 int agg_main(int argc, char* argv[]) 174 { 175 176 177 the_application app(agg::pix_format_bgr24, false); 178 179 app.caption("AGG Example. Anti-Aliasing Demo"); 180 181 if (app.init(600, 400, agg::window_resize)) 182 { 183 return app.run(); 184 } 185 return -1; 186 187 }
编译运行,一切OK的话显示如图
还没完,AGG最叼的是自带演示工程水平非常高,在源码中有一个叫examples的目录,直接拖一个idea.cpp编译,如图
所有例子都有预编译好的二进制版可看,真正良心实用的例子。
http://www.antigrain.com/demo/index.html
好,到此AGG部分就结束了。
========================================
接下来看看Cairo
第三方依懒库有
libpng
zlib
pixman
当然Cairo源码肯定少不了 http://www.cairographics.org/download/
libpng和zlib编译直接使用之前编译好的 http://www.cnblogs.com/kileyi/p/5193823.html
官网有一个说明,但是我没完全照做。
http://www.cairographics.org/end_to_end_build_for_win32/
主要不同的是,我的libpng和zlib编译好了,直接从pixman开始的
首先打开VS2015命令行开发环境,在开始菜单中可以找到
然后进入到pixman源码目录
D:\CPPLibs\pixman-0.34.0\pixman
注意这个不是源码根目录,而是pixman目录,一定不能搞错了
然后新建一个setpath.bat文件,内容如下,主要就是设置一下msys的bin到当前环境目录,并且release编译
set PATH=%PATH%;D:\MinGW\msys\1.0\bin
make -f Makefile.win32 "CFG=release"
之后在命令行中运行这个bat,一切OK会在release目录生成pixman-1.lib,等会儿要用到
3个依赖库都搞定后就要编译Cairo了,我的源码目录
D:\CPPLibs\cairo-1.14.6
然后在与源码目录同级新建libpng,zlib,pixman目录,放上对应的lib文件
D:\CPPLibs\libpng\libpng.lib
D:\CPPLibs\zlib\zdll.lib
D:\CPPLibs\pixman\pixman\release\pixman-1.lib
注意有些需要改名
然后回到源码目录
D:\CPPLibs\cairo-1.14.6
新建setpath.bat文件,内容如下,主要是设置include和library路径,出于一些原因我的libpng和zlib的library放到了一起,你如果没放到一起就自己加上
set INCLUDE=%INCLUDE%;D:\CPPLibs\zlib-1.2.8
set INCLUDE=%INCLUDE%;D:\CPPLibs\lpng1621
set INCLUDE=%INCLUDE%;D:\CPPLibs\pixman-0.34.0\pixman
set INCLUDE=%INCLUDE%;D:\CPPLibs\cairo-1.14.6\boilerplate
set INCLUDE=%INCLUDE%;D:\CPPLibs\cairo-1.14.6\src
set LIB=%LIB%;D:\CPPLibs\lpng1621\projects\vstudio\Release
make -f Makefile.win32 "CFG=release"
有人可能想为什么这里都设置好了路径,上面还要建立libpng和zlib,pixman目录,这主要是因为官方那个编译文件默认是写死的,只找他默认改名后的目录和文件,
我懒得改所以就直接复制了一份,在官方的那个编译说明中好像有提到
如果编译完一切OK,你会看到下面几个需要的文件
D:\CPPLibs\cairo-1.14.6\src\release\cairo.lib
D:\CPPLibs\cairo-1.14.6\src\release\cairo-static.lib
D:\CPPLibs\cairo-1.14.6\src\release\cairo.dll
我只需要cairo.lib和cairo.dll
接下来新建Win32 Console空工程,配置好Cario和OpenGL的include和library目录
使用glut,glext,opengl1.x语法,写个简单的测试工程
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <malloc.h> 4 5 #define _USE_MATH_DEFINES 6 #include <math.h> 7 8 #include <gl/glut.h> 9 #include <gl/glext.h> 10 11 #include <cairo.h> 12 13 14 15 double win_width = 800; 16 double win_height = 600; 17 double hw = win_width / 2; 18 double hh = win_height / 2; 19 double line_width = 5; 20 //double line_width = 1 / win_width; 21 22 cairo_surface_t * surf = NULL; 23 cairo_t * cr = NULL; 24 unsigned char * surf_data = NULL; 25 26 GLuint texture_id; 27 28 // Interface // 29 30 void opengl_init(void) 31 { 32 printf("OpenGL version: %s\n", glGetString(GL_VERSION)); 33 printf("OpenGL vendor: %s\n", glGetString(GL_VENDOR)); 34 printf("OpenGL renderer: %s\n", glGetString(GL_RENDERER)); 35 36 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 37 glDisable(GL_DEPTH_TEST); 38 glEnable(GL_BLEND); 39 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 40 glEnable(GL_TEXTURE_RECTANGLE_ARB); 41 } 42 43 void opengl_cleanup(void) 44 { 45 glDeleteTextures(1, &texture_id); 46 } 47 48 void opengl_draw(int width, int height, unsigned char * surf_data) 49 { 50 if (!surf_data) 51 { 52 printf("draw_func() - No valid pointer to surface-data passed\n"); 53 return; 54 } 55 56 glMatrixMode(GL_MODELVIEW); 57 glLoadIdentity(); 58 glClear(GL_COLOR_BUFFER_BIT); 59 60 glPushMatrix(); 61 62 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id); 63 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 64 0, 65 GL_RGBA, 66 width, 67 height, 68 0, 69 GL_BGRA, 70 GL_UNSIGNED_BYTE, 71 surf_data); 72 73 glColor3f(0.25f, 0.5f, 1.0f); 74 glBegin(GL_QUADS); 75 glTexCoord2f(0.0f, 0.0f); 76 glVertex2f(0.0f, 0.0f); 77 glTexCoord2f((GLfloat)width, 0.0f); 78 glVertex2f(1.0f, 0.0f); 79 glTexCoord2f((GLfloat)width, (GLfloat)height); 80 glVertex2f(1.0f, 1.0f); 81 glTexCoord2f(0.0f, (GLfloat)height); 82 glVertex2f(0.0f, 1.0f); 83 glEnd(); 84 85 glPopMatrix(); 86 } 87 88 void opengl_resize(int width, int height) 89 { 90 glViewport(0, 0, width, height); 91 glMatrixMode(GL_PROJECTION); 92 glLoadIdentity(); 93 glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); 94 95 glClear(GL_COLOR_BUFFER_BIT); 96 97 glDeleteTextures(1, &texture_id); 98 glGenTextures(1, &texture_id); 99 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id); 100 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 101 0, 102 GL_RGBA, 103 width, 104 height, 105 0, 106 GL_BGRA, 107 GL_UNSIGNED_BYTE, 108 NULL); 109 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 110 } 111 112 113 void drawShape() 114 { 115 //save current brush 116 cairo_save(cr); 117 118 // clear background 119 cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 120 //cairo_scale(cr, (double)win_height / 1.0f, (double)win_height / 1.0f); 121 cairo_set_source_rgba(cr, 1, 1, 1, 1); 122 cairo_paint(cr); 123 124 //set line color and style 125 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 126 cairo_set_line_width(cr, line_width); 127 128 129 130 static double angle = 0; 131 angle += 0.01f; 132 133 //画矩形 134 cairo_set_source_rgba(cr, 1, 0, 0, 1); 135 //cairo_rectangle(cr, 0.5f + sinf(angle) * 0.1f, 0.5f, 0.1f, 0.1f); 136 cairo_rectangle(cr, hw + sin(angle) * 100, hh, 100, 100); 137 cairo_fill(cr); 138 cairo_stroke(cr); 139 140 //画弧 141 cairo_set_source_rgba(cr, 0, 0, 1, 1); 142 cairo_arc(cr, 300, hh, 100, 0, 2 * M_PI); 143 //cairo_fill(cr); 144 cairo_stroke(cr); 145 146 //画线 147 static double r = 100; 148 static double posx = 500; 149 static double posy = 500; 150 static double x = 0; 151 static double y = 0; 152 153 x = r * cosf(angle); 154 y = r * sinf(angle); 155 156 cairo_set_source_rgba(cr, 0, 1, 0, 1); 157 cairo_move_to(cr, x + posx, y + posy); 158 cairo_line_to(cr, -x + posx, -y + posy); 159 cairo_stroke(cr); 160 161 162 163 //restore previous brush 164 cairo_restore(cr); 165 } 166 167 168 void display(void) 169 { 170 drawShape(); 171 172 opengl_draw(win_width, win_height, surf_data); 173 174 glutSwapBuffers(); 175 } 176 177 cairo_t* 178 create_cairo_context(int width, 179 int height, 180 int channels, 181 cairo_surface_t** surf, 182 unsigned char** buffer) 183 { 184 cairo_t* cr; 185 186 // create cairo-surface/context to act as OpenGL-texture source 187 *buffer = (unsigned char*)calloc(channels * width * height, sizeof(unsigned char)); 188 if (!*buffer) 189 { 190 printf("create_cairo_context() - Couldn't allocate buffer\n"); 191 return NULL; 192 } 193 194 *surf = cairo_image_surface_create_for_data(*buffer, 195 CAIRO_FORMAT_ARGB32, 196 width, 197 height, 198 channels * width); 199 if (cairo_surface_status(*surf) != CAIRO_STATUS_SUCCESS) 200 { 201 free(*buffer); 202 printf("create_cairo_context() - Couldn't create surface\n"); 203 return NULL; 204 } 205 206 cr = cairo_create(*surf); 207 if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) 208 { 209 free(*buffer); 210 printf("create_cairo_context() - Couldn't create context\n"); 211 return NULL; 212 } 213 214 return cr; 215 } 216 217 void cleanup(void) 218 { 219 opengl_cleanup(); 220 free(surf_data); 221 cairo_destroy(cr); 222 exit(0); 223 } 224 225 void keyboard(unsigned char key, int x, int y) 226 { 227 switch (key) 228 { 229 //27 is ESC key 230 case 27: 231 case 'q': 232 cleanup(); 233 break; 234 235 case 'd': 236 cairo_surface_write_to_png(surf, "frame.png"); 237 break; 238 239 case '+': 240 if (line_width < 10) 241 line_width += 1; 242 break; 243 244 case '-': 245 if (line_width > 1) 246 line_width -= 1; 247 break; 248 249 } 250 } 251 252 void idle(void) 253 { 254 glutPostRedisplay(); 255 } 256 257 int main(int argc, char ** argv) 258 { 259 glutInit(&argc, argv); 260 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); 261 glutInitWindowSize(win_width, win_height); 262 263 if (glutCreateWindow("Opengl Test") == 0) 264 exit(-2); 265 266 // create cairo-surface/context to act as OpenGL-texture source 267 cr = create_cairo_context(win_width, win_height, 4, &surf, &surf_data); 268 269 // setup "GL-context" 270 opengl_init(); 271 272 glutDisplayFunc(display); 273 glutKeyboardFunc(keyboard); 274 glutIdleFunc(idle); 275 opengl_resize(win_width, win_height); 276 277 glutMainLoop(); 278 279 return 0; 280 }
至此Cairo部分就结束了,活动一下筋骨,可以开始写应用了