#include #include #include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_rasterizer_outline.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" #include "agg_scanline_p.h" #include "agg_renderer_scanline.h" #include "agg_renderer_primitives.h" #include "agg_rasterizer_outline.h" #include "agg_rasterizer_outline_aa.h" #include "agg_pattern_filters_rgba.h" #include "agg_renderer_outline_aa.h" #include "agg_renderer_outline_image.h" #include "ctrl/agg_slider_ctrl.h" #include "ctrl/agg_cbox_ctrl.h" #include "platform/agg_platform_support.h" #define AGG_BGR24 //#define AGG_RGB24 //#define AGG_BGRA32 //#define AGG_RGBA32 //#define AGG_ARGB32 //#define AGG_ABGR32 //#define AGG_RGB565 //#define AGG_RGB555 #include "pixel_formats.h" enum flip_y_e { flip_y = true }; static const agg::int32u pixmap_chain[] = { 16, 7, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff975252, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xa4c7a2a2, 0x3affff00, 0x3affff00, 0xff975151, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff954f4f, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff }; namespace agg { class pattern_pixmap_argb32 { public: typedef rgba color_type; pattern_pixmap_argb32(const int32u* pixmap) : m_pixmap(pixmap) {} unsigned width() const { return m_pixmap[0]; } unsigned height() const { return m_pixmap[1]; } rgba pixel(int x, int y) const { int32u p = m_pixmap[y * width() + x + 2]; srgba8 c((p >> 16) & 0xFF, (p >> 8) & 0xFF, p & 0xFF, p >> 24); return rgba(c).premultiply(); } private: const int32u* m_pixmap; }; } class spiral { public: spiral(double x, double y, double r1, double r2, double step, double start_angle=0) : m_x(x), m_y(y), m_r1(r1), m_r2(r2), m_step(step), m_start_angle(start_angle), m_angle(start_angle), m_da(agg::deg2rad(8.0)), m_dr(m_step / 45.0) { } void rewind(unsigned) { m_angle = m_start_angle; m_curr_r = m_r1; m_start = true; } unsigned vertex(double* x, double* y) { if(m_curr_r > m_r2) return agg::path_cmd_stop; *x = m_x + cos(m_angle) * m_curr_r; *y = m_y + sin(m_angle) * m_curr_r; m_curr_r += m_dr; m_angle += m_da; if(m_start) { m_start = false; return agg::path_cmd_move_to; } return agg::path_cmd_line_to; } private: double m_x; double m_y; double m_r1; double m_r2; double m_step; double m_start_angle; double m_angle; double m_curr_r; double m_da; double m_dr; bool m_start; }; struct roundoff { void transform(double* x, double* y) const { *x = floor(*x); *y = floor(*y); } }; class the_application : public agg::platform_support { agg::slider_ctrl m_step; agg::slider_ctrl m_width; agg::cbox_ctrl m_test; agg::cbox_ctrl m_rotate; agg::cbox_ctrl m_accurate_joins; agg::cbox_ctrl m_scale_pattern; double m_start_angle; public: typedef agg::renderer_base renderer_base; typedef agg::renderer_scanline_aa_solid renderer_aa; typedef agg::renderer_primitives renderer_prim; typedef agg::rasterizer_outline rasterizer_outline; typedef agg::rasterizer_scanline_aa<> rasterizer_scanline; typedef agg::scanline_p8 scanline; typedef agg::renderer_outline_aa renderer_oaa; typedef agg::pattern_filter_bilinear_rgba pattern_filter; typedef agg::line_image_pattern_pow2 image_pattern; typedef agg::renderer_outline_image renderer_img; typedef agg::rasterizer_outline_aa rasterizer_outline_aa; typedef agg::rasterizer_outline_aa rasterizer_outline_img; the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), m_step(10.0, 10.0 + 4.0, 150.0, 10.0 + 8.0 + 4.0, !flip_y), m_width(150.0 + 10.0, 10.0 + 4.0, 400 - 10.0, 10.0 + 8.0 + 4.0, !flip_y), m_test(10.0, 10.0 + 4.0 + 16.0, "Test Performance", !flip_y), m_rotate(130 + 10.0, 10.0 + 4.0 + 16.0, "Rotate", !flip_y), m_accurate_joins(200 + 10.0, 10.0 + 4.0 + 16.0, "Accurate Joins", !flip_y), m_scale_pattern(310 + 10.0, 10.0 + 4.0 + 16.0, "Scale Pattern", !flip_y), m_start_angle(0.0) { add_ctrl(m_step); m_step.range(0.0, 2.0); m_step.value(0.1); m_step.label("Step=%1.2f"); m_step.no_transform(); add_ctrl(m_width); m_width.range(0.0, 14.0); m_width.value(3.0); m_width.label("Width=%1.2f"); m_width.no_transform(); add_ctrl(m_test); m_test.text_size(9.0, 7.0); m_test.no_transform(); add_ctrl(m_rotate); m_rotate.text_size(9.0, 7.0); m_rotate.no_transform(); add_ctrl(m_accurate_joins); m_accurate_joins.text_size(9.0, 7.0); m_accurate_joins.no_transform(); add_ctrl(m_scale_pattern); m_scale_pattern.text_size(9.0, 7.0); m_scale_pattern.no_transform(); m_scale_pattern.status(true); } void draw_aliased_pix_accuracy(rasterizer_outline& ras, renderer_prim& prim) { spiral s1(width()/5, height()/4+50, 5, 70, 16, m_start_angle); roundoff rn; agg::conv_transform trans(s1, rn); prim.line_color(agg::rgba(0.4, 0.3, 0.1)); ras.add_path(trans); } void draw_aliased_subpix_accuracy(rasterizer_outline& ras, renderer_prim& prim) { spiral s2(width()/2, height()/4+50, 5, 70, 16, m_start_angle); prim.line_color(agg::rgba(0.4, 0.3, 0.1)); ras.add_path(s2); } void draw_anti_aliased_outline(rasterizer_outline_aa& ras, renderer_oaa& ren) { spiral s3(width()/5, height() - height()/4 + 20, 5, 70, 16, m_start_angle); ren.color(agg::rgba(0.4, 0.3, 0.1)); ras.add_path(s3); } void draw_anti_aliased_scanline(rasterizer_scanline& ras, scanline& sl, renderer_aa& ren) { spiral s4(width()/2, height() - height()/4 + 20, 5, 70, 16, m_start_angle); agg::conv_stroke stroke(s4); stroke.width(m_width.value()); stroke.line_cap(agg::round_cap); ren.color(agg::rgba(0.4, 0.3, 0.1)); ras.add_path(stroke); agg::render_scanlines(ras, sl, ren); } void draw_anti_aliased_outline_img(rasterizer_outline_img& ras, renderer_img& ren) { spiral s5(width() - width()/5, height() - height()/4 + 20, 5, 70, 16, m_start_angle); ras.add_path(s5); } void text(rasterizer_scanline& ras, scanline& sl, renderer_aa& ren, double x, double y, const char* txt) { agg::gsv_text t; t.size(8); t.text(txt); t.start_point(x, y); agg::conv_stroke stroke(t); stroke.width(0.7); ras.add_path(stroke); ren.color(agg::rgba(0,0,0)); agg::render_scanlines(ras, sl, ren); } virtual void on_draw() { pixfmt_pre pf(rbuf_window()); renderer_base ren_base(pf); renderer_aa ren_aa(ren_base); renderer_prim ren_prim(ren_base); rasterizer_scanline ras_aa; scanline sl; rasterizer_outline ras_al(ren_prim); agg::line_profile_aa prof; prof.width(m_width.value()); renderer_oaa ren_oaa(ren_base, prof); rasterizer_outline_aa ras_oaa(ren_oaa); ras_oaa.line_join(m_accurate_joins.status() ? agg::outline_miter_accurate_join : agg::outline_round_join); ras_oaa.round_cap(true); pattern_filter filter; agg::pattern_pixmap_argb32 src(pixmap_chain); agg::line_image_scale src_scaled(src, m_width.value()); image_pattern pattern(filter); if(m_scale_pattern.status()) { pattern.create(src_scaled); } else { pattern.create(src); } renderer_img ren_img(ren_base, pattern); if(m_scale_pattern.status()) { ren_img.scale_x(m_width.value() / src.height()); } rasterizer_outline_img ras_img(ren_img); ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); draw_aliased_pix_accuracy(ras_al, ren_prim); draw_aliased_subpix_accuracy(ras_al, ren_prim); draw_anti_aliased_outline(ras_oaa, ren_oaa); draw_anti_aliased_scanline(ras_aa, sl, ren_aa); draw_anti_aliased_outline_img(ras_img, ren_img); text(ras_aa, sl, ren_aa, 50, 80, "Bresenham lines,\n\nregular accuracy"); text(ras_aa, sl, ren_aa, width()/2-50, 80, "Bresenham lines,\n\nsubpixel accuracy"); text(ras_aa, sl, ren_aa, 50, height()/2+50, "Anti-aliased lines"); text(ras_aa, sl, ren_aa, width()/2-50, height()/2+50, "Scanline rasterizer"); text(ras_aa, sl, ren_aa, width() - width()/5 - 50, height()/2+50, "Arbitrary Image Pattern"); // The source colors of controls are "plain". pixfmt pf2(rbuf_window()); agg::renderer_base ren_base2(pf2); agg::render_ctrl(ras_aa, sl, ren_base2, m_step); agg::render_ctrl(ras_aa, sl, ren_base2, m_width); agg::render_ctrl(ras_aa, sl, ren_base2, m_test); agg::render_ctrl(ras_aa, sl, ren_base2, m_rotate); agg::render_ctrl(ras_aa, sl, ren_base2, m_accurate_joins); agg::render_ctrl(ras_aa, sl, ren_base2, m_scale_pattern); /* // An example of using anti-aliased outline rasterizer. // Uncomment it to see the result // // Includes: //#include "agg_pixfmt_rgb.h" // or another //#include "agg_renderer_outline_aa.h" //#include "agg_rasterizer_outline_aa.h" typedef agg::renderer_base base_ren_type; typedef agg::renderer_outline_aa renderer_type; typedef agg::rasterizer_outline_aa rasterizer_type; double width = 5.0; //-- create with specifying width //-- min_width=1.0, smoother_width=1.0 //agg::line_profile_aa(width, agg::gamma_none()); //-- create uninitialized and set parameters agg::line_profile_aa profile; profile.gamma(agg::gamma_power(1.2)); //optional profile.min_width(0.75); //optional profile.smoother_width(3.0); //optional profile.width(width); //mandatory! agg::pixfmt_bgr24 pixf(rbuf_window()); //or another base_ren_type base_ren(pixf); renderer_type ren(base_ren, profile); ren.color(agg::srgba8(0,0,0)); //mandatory! rasterizer_type ras(ren); ras.round_cap(true); //optional ras.accurate_join(true); //optional //-- move_to/line_to interface ras.move_to_d(100, 100); ras.line_to_d(150, 200); ras.render(false); //false means "don't close //the polygon", i.e. polyline //-- add_path interface //-- doesn't require invoking render() //ras.add_path(some_path); */ /* // An example of using image pattern outline rasterizer // Uncomment it to see the result // // Includes: //#include "agg_pixfmt_rgb.h" // or another //#include "agg_pattern_filters_rgba.h" // for all rgba-8-bit color formats //#include "agg_renderer_outline_image.h" //#include "agg_rasterizer_outline_aa.h" agg::pattern_filter_bilinear_rgba8 fltr; // Filtering functor agg::pattern_pixmap_argb32 patt_src(pixmap_chain); // Source. Must have an interface: // width() const // height() const // pixel(int x, int y) const // Any agg::renderer_base<> or derived // is good for the use as a source. // agg::line_image_pattern is the main container for the patterns. It creates // a copy of the patterns extended according to the needs of the filter. // agg::line_image_pattern can operate with arbitrary image width, but if the // width of the pattern is power of 2, it's better to use the modified // version agg::line_image_pattern_pow2 because it works about 15-25 percent // faster than agg::line_image_pattern (because of using simple masking instead // of expensive '%' operation). typedef agg::line_image_pattern_pow2 pattern_type; typedef agg::renderer_base base_ren_type; typedef agg::renderer_outline_image renderer_type; typedef agg::rasterizer_outline_aa rasterizer_type; //-- Create with specifying the source pattern_type patt(fltr, src); //-- Create uninitialized and set the source //pattern_type patt(fltr); //patt.create(src); agg::pixfmt_bgr24 pixf(rbuf_window()); //or another base_ren_type base_ren(pixf); renderer_type ren(base_ren, patt); //ren.scale_x(1.3); // Optional rasterizer_type ras(ren); //-- move_to/line_to interface ras.move_to_d(100, 150); ras.line_to_d(0, 0); ras.line_to_d(300, 200); //ras.line_to_d(10, 10); ras.render(false); //false means "don't close //the polygon", i.e. polyline //-- add_path interface //-- doesn't require invoking render() //ras.add_path(some_path); */ } virtual void on_idle() { m_start_angle += agg::deg2rad(m_step.value()); if(m_start_angle > agg::deg2rad(360.0)) m_start_angle -= agg::deg2rad(360.0); force_redraw(); } virtual void on_ctrl_change() { wait_mode(!m_rotate.status()); if(m_test.status()) { on_draw(); update_window(); pixfmt_pre pf(rbuf_window()); renderer_base ren_base(pf); renderer_aa ren_aa(ren_base); renderer_prim ren_prim(ren_base); rasterizer_scanline ras_aa; scanline sl; rasterizer_outline ras_al(ren_prim); agg::line_profile_aa prof; prof.width(m_width.value()); renderer_oaa ren_oaa(ren_base, prof); rasterizer_outline_aa ras_oaa(ren_oaa); ras_oaa.line_join(m_accurate_joins.status() ? agg::outline_miter_accurate_join : agg::outline_round_join); ras_oaa.round_cap(true); pattern_filter filter; agg::pattern_pixmap_argb32 src(pixmap_chain); agg::line_image_scale src_scaled(src, m_width.value()); image_pattern pattern(filter); if(m_scale_pattern.status()) { pattern.create(src_scaled); } else { pattern.create(src); } renderer_img ren_img(ren_base, pattern); if(m_scale_pattern.status()) { ren_img.scale_x(src.height() / m_width.value()); } rasterizer_outline_img ras_img(ren_img); unsigned i; start_timer(); for(i = 0; i < 200; i++) { draw_aliased_subpix_accuracy(ras_al, ren_prim); m_start_angle += agg::deg2rad(m_step.value()); } double t2 = elapsed_time(); start_timer(); for(i = 0; i < 200; i++) { draw_anti_aliased_outline(ras_oaa, ren_oaa); m_start_angle += agg::deg2rad(m_step.value()); } double t3 = elapsed_time(); start_timer(); for(i = 0; i < 200; i++) { draw_anti_aliased_scanline(ras_aa, sl, ren_aa); m_start_angle += agg::deg2rad(m_step.value()); } double t4 = elapsed_time(); start_timer(); for(i = 0; i < 200; i++) { draw_anti_aliased_outline_img(ras_img, ren_img); m_start_angle += agg::deg2rad(m_step.value()); } double t5 = elapsed_time(); m_test.status(false); force_redraw(); char buf[256]; sprintf(buf, "Aliased=%1.2fms, Anti-Aliased=%1.2fms, Scanline=%1.2fms, Image-Pattern=%1.2fms", t2, t3, t4, t5); message(buf); } } }; int agg_main(int argc, char* argv[]) { the_application app(pix_format, flip_y); app.caption("AGG Example. Line Join"); if(app.init(500, 450, 0)) { return app.run(); } return 1; }