00001 #include <stdio.h>
00002 #include "agg_basics.h"
00003 #include "agg_rendering_buffer.h"
00004 #include "agg_rasterizer_scanline_aa.h"
00005 #include "agg_scanline_p.h"
00006 #include "agg_renderer_scanline.h"
00007 #include "agg_renderer_primitives.h"
00008 #include "agg_conv_curve.h"
00009 #include "agg_conv_stroke.h"
00010 #include "agg_gsv_text.h"
00011 #include "agg_pixfmt_rgb.h"
00012 #include "agg_pixfmt_gray.h"
00013 #include "agg_pixfmt_amask_adaptor.h"
00014 #include "agg_span_allocator.h"
00015 #include "agg_alpha_mask_u8.h"
00016
00017 #include "platform/agg_platform_support.h"
00018
00019 #include "ctrl/agg_slider_ctrl.h"
00020 #include "ctrl/agg_cbox_ctrl.h"
00021 #include "ctrl/agg_rbox_ctrl.h"
00022
00023
00024 enum flip_y_e { flip_y = true };
00025
00026
00027
00028
00029 class spiral
00030 {
00031 public:
00032 spiral(double x, double y, double r1, double r2, double step, double start_angle=0) :
00033 m_x(x),
00034 m_y(y),
00035 m_r1(r1),
00036 m_r2(r2),
00037 m_step(step),
00038 m_start_angle(start_angle),
00039 m_angle(start_angle),
00040 m_da(agg::deg2rad(4.0)),
00041 m_dr(m_step / 90.0)
00042 {
00043 }
00044
00045 void rewind(unsigned)
00046 {
00047 m_angle = m_start_angle;
00048 m_curr_r = m_r1;
00049 m_start = true;
00050 }
00051
00052 unsigned vertex(double* x, double* y)
00053 {
00054 if(m_curr_r > m_r2) return agg::path_cmd_stop;
00055
00056 *x = m_x + cos(m_angle) * m_curr_r;
00057 *y = m_y + sin(m_angle) * m_curr_r;
00058 m_curr_r += m_dr;
00059 m_angle += m_da;
00060 if(m_start)
00061 {
00062 m_start = false;
00063 return agg::path_cmd_move_to;
00064 }
00065 return agg::path_cmd_line_to;
00066 }
00067
00068 private:
00069 double m_x;
00070 double m_y;
00071 double m_r1;
00072 double m_r2;
00073 double m_step;
00074 double m_start_angle;
00075
00076 double m_angle;
00077 double m_curr_r;
00078 double m_da;
00079 double m_dr;
00080 bool m_start;
00081 };
00082
00083
00084
00085
00086
00087 void make_gb_poly(agg::path_storage& ps);
00088 void make_arrows(agg::path_storage& ps);
00089
00090
00091 class the_application : public agg::platform_support
00092 {
00093 agg::rbox_ctrl<agg::rgba8> m_polygons;
00094 agg::rbox_ctrl<agg::rgba8> m_operation;
00095
00096 typedef agg::amask_no_clip_gray8 alpha_mask_type;
00097
00098
00099 typedef agg::pixfmt_bgr24 pixfmt_type;
00100
00101 unsigned char* m_alpha_buf;
00102 agg::rendering_buffer m_alpha_mask_rbuf;
00103 alpha_mask_type m_alpha_mask;
00104 agg::rasterizer_scanline_aa<> m_ras;
00105 agg::scanline_p8 m_sl;
00106
00107 double m_x;
00108 double m_y;
00109
00110 public:
00111 ~the_application()
00112 {
00113 delete [] m_alpha_buf;
00114 }
00115
00116 the_application(agg::pix_format_e format, bool flip_y) :
00117 agg::platform_support(format, flip_y),
00118 m_polygons (5.0, 5.0, 5.0+205.0, 110.0, !flip_y),
00119 m_operation(555.0, 5.0, 555.0+80.0, 55.0, !flip_y),
00120 m_alpha_buf(0),
00121 m_alpha_mask_rbuf(),
00122 m_alpha_mask(m_alpha_mask_rbuf),
00123 m_x(0),
00124 m_y(0)
00125 {
00126 m_operation.add_item("AND");
00127 m_operation.add_item("SUB");
00128 m_operation.cur_item(0);
00129 add_ctrl(m_operation);
00130 m_operation.no_transform();
00131
00132 m_polygons.add_item("Two Simple Paths");
00133 m_polygons.add_item("Closed Stroke");
00134 m_polygons.add_item("Great Britain and Arrows");
00135 m_polygons.add_item("Great Britain and Spiral");
00136 m_polygons.add_item("Spiral and Glyph");
00137 m_polygons.cur_item(3);
00138 add_ctrl(m_polygons);
00139 m_polygons.no_transform();
00140 }
00141
00142
00143 void draw_text(double x, double y, const char* str)
00144 {
00145 pixfmt_type pf(rbuf_window());
00146 agg::renderer_base<pixfmt_type> rb(pf);
00147 agg::renderer_scanline_aa_solid<agg::renderer_base<pixfmt_type> > ren(rb);
00148
00149 agg::gsv_text txt;
00150 agg::conv_stroke<agg::gsv_text> txt_stroke(txt);
00151 txt_stroke.width(1.5);
00152 txt_stroke.line_cap(agg::round_cap);
00153 txt.size(10.0);
00154 txt.start_point(x, y);
00155 txt.text(str);
00156 m_ras.add_path(txt_stroke);
00157 ren.color(agg::rgba(0.0, 0.0, 0.0));
00158 agg::render_scanlines(m_ras, m_sl, ren);
00159 }
00160
00161
00162 template<class VertexSource> void generate_alpha_mask(VertexSource& vs)
00163 {
00164 unsigned cx = (unsigned)width();
00165 unsigned cy = (unsigned)height();
00166
00167 delete [] m_alpha_buf;
00168 m_alpha_buf = new unsigned char[cx * cy];
00169 m_alpha_mask_rbuf.attach(m_alpha_buf, cx, cy, cx);
00170
00171 typedef agg::renderer_base<agg::pixfmt_gray8> ren_base;
00172 typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
00173
00174 agg::pixfmt_gray8 pixf(m_alpha_mask_rbuf);
00175 ren_base rb(pixf);
00176 renderer ren(rb);
00177
00178 start_timer();
00179 if(m_operation.cur_item() == 0)
00180 {
00181 rb.clear(agg::gray8(0));
00182 ren.color(agg::gray8(255));
00183 }
00184 else
00185 {
00186 rb.clear(agg::gray8(255));
00187 ren.color(agg::gray8(0));
00188 }
00189 m_ras.add_path(vs);
00190 agg::render_scanlines(m_ras, m_sl, ren);
00191 double t1 = elapsed_time();
00192
00193 char buf[100];
00194 sprintf(buf, "Generate AlphaMask: %.3fms", t1);
00195 draw_text(250, 20, buf);
00196 }
00197
00198
00199 template<class VertexSource>
00200 void perform_rendering(VertexSource& vs)
00201 {
00202 pixfmt_type pixf(rbuf_window());
00203
00204 typedef agg::pixfmt_amask_adaptor<pixfmt_type, alpha_mask_type> pixfmt_amask_type;
00205 typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
00206
00207
00208 pixfmt_amask_type pixfa(pixf, m_alpha_mask);
00209 amask_ren_type rbase(pixfa);
00210 agg::renderer_scanline_aa_solid<amask_ren_type> ren(rbase);
00211
00212 ren.color(agg::rgba(0.5, 0.0, 0, 0.5));
00213
00214 start_timer();
00215 m_ras.reset();
00216 m_ras.add_path(vs);
00217 agg::render_scanlines(m_ras, m_sl, ren);
00218 double t1 = elapsed_time();
00219
00220
00221 char buf[100];
00222 sprintf(buf, "Render with AlphaMask: %.3fms", t1);
00223 draw_text(250, 5, buf);
00224 }
00225
00226
00227 unsigned render()
00228 {
00229 pixfmt_type pf(rbuf_window());
00230 agg::renderer_base<pixfmt_type> rb(pf);
00231 agg::renderer_scanline_aa_solid<agg::renderer_base<pixfmt_type> > ren(rb);
00232
00233 switch(m_polygons.cur_item())
00234 {
00235 case 0:
00236 {
00237
00238
00239
00240 agg::path_storage ps1;
00241 agg::path_storage ps2;
00242
00243 double x = m_x - initial_width()/2 + 100;
00244 double y = m_y - initial_height()/2 + 100;
00245 ps1.move_to(x+140, y+145);
00246 ps1.line_to(x+225, y+44);
00247 ps1.line_to(x+296, y+219);
00248 ps1.close_polygon();
00249
00250 ps1.line_to(x+226, y+289);
00251 ps1.line_to(x+82, y+292);
00252
00253 ps1.move_to(x+220, y+222);
00254 ps1.line_to(x+363, y+249);
00255 ps1.line_to(x+265, y+331);
00256
00257 ps1.move_to(x+242, y+243);
00258 ps1.line_to(x+268, y+309);
00259 ps1.line_to(x+325, y+261);
00260
00261 ps1.move_to(x+259, y+259);
00262 ps1.line_to(x+273, y+288);
00263 ps1.line_to(x+298, y+266);
00264
00265 ps2.move_to(100+32, 100+77);
00266 ps2.line_to(100+473, 100+263);
00267 ps2.line_to(100+351, 100+290);
00268 ps2.line_to(100+354, 100+374);
00269
00270 m_ras.reset();
00271 m_ras.add_path(ps1);
00272 ren.color(agg::rgba(0, 0, 0, 0.1));
00273 agg::render_scanlines(m_ras, m_sl, ren);
00274
00275 m_ras.reset();
00276 m_ras.add_path(ps2);
00277 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00278 agg::render_scanlines(m_ras, m_sl, ren);
00279
00280 generate_alpha_mask(ps1);
00281 perform_rendering(ps2);
00282 }
00283 break;
00284
00285 case 1:
00286 {
00287
00288
00289
00290 agg::path_storage ps1;
00291 agg::path_storage ps2;
00292 agg::conv_stroke<agg::path_storage> stroke(ps2);
00293 stroke.width(10.0);
00294
00295 double x = m_x - initial_width()/2 + 100;
00296 double y = m_y - initial_height()/2 + 100;
00297 ps1.move_to(x+140, y+145);
00298 ps1.line_to(x+225, y+44);
00299 ps1.line_to(x+296, y+219);
00300 ps1.close_polygon();
00301
00302 ps1.line_to(x+226, y+289);
00303 ps1.line_to(x+82, y+292);
00304
00305 ps1.move_to(x+220-50, y+222);
00306 ps1.line_to(x+265-50, y+331);
00307 ps1.line_to(x+363-50, y+249);
00308 ps1.close_polygon(agg::path_flags_ccw);
00309
00310 ps2.move_to(100+32, 100+77);
00311 ps2.line_to(100+473, 100+263);
00312 ps2.line_to(100+351, 100+290);
00313 ps2.line_to(100+354, 100+374);
00314 ps2.close_polygon();
00315
00316 m_ras.reset();
00317 m_ras.add_path(ps1);
00318 ren.color(agg::rgba(0, 0, 0, 0.1));
00319 agg::render_scanlines(m_ras, m_sl, ren);
00320
00321 m_ras.reset();
00322 m_ras.add_path(stroke);
00323 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00324 agg::render_scanlines(m_ras, m_sl, ren);
00325
00326 generate_alpha_mask(ps1);
00327 perform_rendering(stroke);
00328 }
00329 break;
00330
00331
00332 case 2:
00333 {
00334
00335
00336
00337 agg::path_storage gb_poly;
00338 agg::path_storage arrows;
00339 make_gb_poly(gb_poly);
00340 make_arrows(arrows);
00341
00342 agg::trans_affine mtx1;
00343 agg::trans_affine mtx2;
00344 mtx1 *= agg::trans_affine_translation(-1150, -1150);
00345 mtx1 *= agg::trans_affine_scaling(2.0);
00346
00347 mtx2 = mtx1;
00348 mtx2 *= agg::trans_affine_translation(m_x - initial_width()/2,
00349 m_y - initial_height()/2);
00350
00351 agg::conv_transform<agg::path_storage> trans_gb_poly(gb_poly, mtx1);
00352 agg::conv_transform<agg::path_storage> trans_arrows(arrows, mtx2);
00353
00354 m_ras.add_path(trans_gb_poly);
00355 ren.color(agg::rgba(0.5, 0.5, 0, 0.1));
00356 agg::render_scanlines(m_ras, m_sl, ren);
00357
00358 agg::conv_stroke<agg::conv_transform<agg::path_storage> > stroke_gb_poly(trans_gb_poly);
00359 stroke_gb_poly.width(0.1);
00360 m_ras.add_path(stroke_gb_poly);
00361 ren.color(agg::rgba(0, 0, 0));
00362 agg::render_scanlines(m_ras, m_sl, ren);
00363
00364 m_ras.add_path(trans_arrows);
00365 ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1));
00366 agg::render_scanlines(m_ras, m_sl, ren);
00367
00368 generate_alpha_mask(trans_gb_poly);
00369 perform_rendering(trans_arrows);
00370 }
00371 break;
00372
00373
00374 case 3:
00375 {
00376
00377
00378
00379 spiral sp(m_x, m_y, 10, 150, 30, 0.0);
00380 agg::conv_stroke<spiral> stroke(sp);
00381 stroke.width(15.0);
00382
00383 agg::path_storage gb_poly;
00384 make_gb_poly(gb_poly);
00385
00386 agg::trans_affine mtx;
00387 mtx *= agg::trans_affine_translation(-1150, -1150);
00388 mtx *= agg::trans_affine_scaling(2.0);
00389
00390 agg::conv_transform<agg::path_storage> trans_gb_poly(gb_poly, mtx);
00391
00392 m_ras.add_path(trans_gb_poly);
00393 ren.color(agg::rgba(0.5, 0.5, 0, 0.1));
00394 agg::render_scanlines(m_ras, m_sl, ren);
00395
00396 agg::conv_stroke<agg::conv_transform<agg::path_storage> > stroke_gb_poly(trans_gb_poly);
00397 stroke_gb_poly.width(0.1);
00398 m_ras.add_path(stroke_gb_poly);
00399 ren.color(agg::rgba(0, 0, 0));
00400 agg::render_scanlines(m_ras, m_sl, ren);
00401
00402 m_ras.add_path(stroke);
00403 ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1));
00404 agg::render_scanlines(m_ras, m_sl, ren);
00405
00406 generate_alpha_mask(trans_gb_poly);
00407 perform_rendering(stroke);
00408 }
00409 break;
00410
00411
00412 case 4:
00413 {
00414
00415
00416
00417 spiral sp(m_x, m_y, 10, 150, 30, 0.0);
00418 agg::conv_stroke<spiral> stroke(sp);
00419 stroke.width(15.0);
00420
00421 agg::path_storage glyph;
00422 glyph.move_to(28.47, 6.45);
00423 glyph.curve3(21.58, 1.12, 19.82, 0.29);
00424 glyph.curve3(17.19, -0.93, 14.21, -0.93);
00425 glyph.curve3(9.57, -0.93, 6.57, 2.25);
00426 glyph.curve3(3.56, 5.42, 3.56, 10.60);
00427 glyph.curve3(3.56, 13.87, 5.03, 16.26);
00428 glyph.curve3(7.03, 19.58, 11.99, 22.51);
00429 glyph.curve3(16.94, 25.44, 28.47, 29.64);
00430 glyph.line_to(28.47, 31.40);
00431 glyph.curve3(28.47, 38.09, 26.34, 40.58);
00432 glyph.curve3(24.22, 43.07, 20.17, 43.07);
00433 glyph.curve3(17.09, 43.07, 15.28, 41.41);
00434 glyph.curve3(13.43, 39.75, 13.43, 37.60);
00435 glyph.line_to(13.53, 34.77);
00436 glyph.curve3(13.53, 32.52, 12.38, 31.30);
00437 glyph.curve3(11.23, 30.08, 9.38, 30.08);
00438 glyph.curve3(7.57, 30.08, 6.42, 31.35);
00439 glyph.curve3(5.27, 32.62, 5.27, 34.81);
00440 glyph.curve3(5.27, 39.01, 9.57, 42.53);
00441 glyph.curve3(13.87, 46.04, 21.63, 46.04);
00442 glyph.curve3(27.59, 46.04, 31.40, 44.04);
00443 glyph.curve3(34.28, 42.53, 35.64, 39.31);
00444 glyph.curve3(36.52, 37.21, 36.52, 30.71);
00445 glyph.line_to(36.52, 15.53);
00446 glyph.curve3(36.52, 9.13, 36.77, 7.69);
00447 glyph.curve3(37.01, 6.25, 37.57, 5.76);
00448 glyph.curve3(38.13, 5.27, 38.87, 5.27);
00449 glyph.curve3(39.65, 5.27, 40.23, 5.62);
00450 glyph.curve3(41.26, 6.25, 44.19, 9.18);
00451 glyph.line_to(44.19, 6.45);
00452 glyph.curve3(38.72, -0.88, 33.74, -0.88);
00453 glyph.curve3(31.35, -0.88, 29.93, 0.78);
00454 glyph.curve3(28.52, 2.44, 28.47, 6.45);
00455 glyph.close_polygon();
00456
00457 glyph.move_to(28.47, 9.62);
00458 glyph.line_to(28.47, 26.66);
00459 glyph.curve3(21.09, 23.73, 18.95, 22.51);
00460 glyph.curve3(15.09, 20.36, 13.43, 18.02);
00461 glyph.curve3(11.77, 15.67, 11.77, 12.89);
00462 glyph.curve3(11.77, 9.38, 13.87, 7.06);
00463 glyph.curve3(15.97, 4.74, 18.70, 4.74);
00464 glyph.curve3(22.41, 4.74, 28.47, 9.62);
00465 glyph.close_polygon();
00466
00467 agg::trans_affine mtx;
00468 mtx *= agg::trans_affine_scaling(4.0);
00469 mtx *= agg::trans_affine_translation(220, 200);
00470 agg::conv_transform<agg::path_storage> trans(glyph, mtx);
00471 agg::conv_curve<agg::conv_transform<agg::path_storage> > curve(trans);
00472
00473 m_ras.reset();
00474 m_ras.add_path(stroke);
00475 ren.color(agg::rgba(0, 0, 0, 0.1));
00476 agg::render_scanlines(m_ras, m_sl, ren);
00477
00478 m_ras.reset();
00479 m_ras.add_path(curve);
00480 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00481 agg::render_scanlines(m_ras, m_sl, ren);
00482
00483 generate_alpha_mask(stroke);
00484 perform_rendering(curve);
00485 }
00486 break;
00487 }
00488
00489 return 0;
00490 }
00491
00492
00493 virtual void on_init()
00494 {
00495 m_x = width() / 2.0;
00496 m_y = height() / 2.0;
00497 }
00498
00499 virtual void on_draw()
00500 {
00501 typedef agg::renderer_base<pixfmt_type> base_ren_type;
00502
00503 pixfmt_type pf(rbuf_window());
00504 base_ren_type ren_base(pf);
00505 ren_base.clear(agg::rgba(1,1,1));
00506
00507 render();
00508
00509 agg::render_ctrl(m_ras, m_sl, ren_base, m_polygons);
00510 agg::render_ctrl(m_ras, m_sl, ren_base, m_operation);
00511 }
00512
00513
00514
00515
00516 virtual void on_mouse_button_down(int x, int y, unsigned flags)
00517 {
00518 if(flags & agg::mouse_left)
00519 {
00520 m_x = x;
00521 m_y = y;
00522 force_redraw();
00523 }
00524
00525 if(flags & agg::mouse_right)
00526 {
00527 char buf[100];
00528 sprintf(buf, "%d %d", x, y);
00529 message(buf);
00530 }
00531 }
00532
00533
00534 virtual void on_mouse_move(int x, int y, unsigned flags)
00535 {
00536 if(flags & agg::mouse_left)
00537 {
00538 m_x = x;
00539 m_y = y;
00540 force_redraw();
00541 }
00542 }
00543
00544
00545
00546 };
00547
00548
00549
00550 int agg_main(int argc, char* argv[])
00551 {
00552 the_application app(agg::pix_format_bgr24, flip_y);
00553 app.caption("AGG Example. Alpha-Mask as a Polygon Clipper");
00554
00555 if(app.init(640, 520, agg::window_resize))
00556 {
00557 return app.run();
00558 }
00559 return 1;
00560 }
00561
00562