#include #include #include #include "agg_basics.h" #include "agg_rendering_buffer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_u.h" #include "agg_color_gray.h" #include "agg_renderer_mclip.h" #include "agg_renderer_scanline.h" #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_bounding_rect.h" #include "agg_renderer_outline_aa.h" #include "agg_renderer_primitives.h" #include "agg_renderer_markers.h" #include "agg_span_allocator.h" #include "agg_span_gradient.h" #include "agg_span_interpolator_linear.h" #include "agg_rasterizer_outline_aa.h" #include "agg_ellipse.h" #include "ctrl/agg_slider_ctrl.h" #include "platform/agg_platform_support.h" //#define AGG_GRAY8 //#define AGG_GRAY16 //#define AGG_GRAY32 #define AGG_BGR24 //#define AGG_RGB24 //#define AGG_BGRA32 //#define AGG_RGBA32 //#define AGG_ARGB32 //#define AGG_ABGR32 //#define AGG_BGR96 //#define AGG_BGRA128 //#define AGG_RGB565 //#define AGG_RGB555 #include "pixel_formats.h" enum flip_y_e { flip_y = true }; agg::rasterizer_scanline_aa<> g_rasterizer; agg::scanline_u8 g_scanline; agg::path_storage g_path; agg::srgba8 g_colors[100]; unsigned g_path_idx[100]; unsigned g_npaths = 0; double g_x1 = 0; double g_y1 = 0; double g_x2 = 0; double g_y2 = 0; double g_base_dx = 0; double g_base_dy = 0; double g_angle = 0; double g_scale = 1.0; double g_skew_x = 0; double g_skew_y = 0; int g_nclick = 0; unsigned parse_lion(agg::path_storage& ps, agg::srgba8* colors, unsigned* path_idx); void parse_lion() { g_npaths = parse_lion(g_path, g_colors, g_path_idx); agg::pod_array_adaptor path_idx(g_path_idx, 100); agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); g_base_dx = (g_x2 - g_x1) / 2.0; g_base_dy = (g_y2 - g_y1) / 2.0; } namespace agg { // Specializations of the gradient_linear_color for srgba8 and sgray8 // color types. Only for the sake of performance. //======================================================================== template<> struct gradient_linear_color { typedef srgba8 color_type; gradient_linear_color() {} gradient_linear_color(const color_type& c1, const color_type& c2) : m_c1(c1), m_c2(c2) {} static unsigned size() { return 256; } color_type operator [] (unsigned v) const { color_type c; c.r = (int8u)((((m_c2.r - m_c1.r) * int(v)) + (m_c1.r << 8)) >> 8); c.g = (int8u)((((m_c2.g - m_c1.g) * int(v)) + (m_c1.g << 8)) >> 8); c.b = (int8u)((((m_c2.b - m_c1.b) * int(v)) + (m_c1.b << 8)) >> 8); c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); return c; } void colors(const color_type& c1, const color_type& c2) { m_c1 = c1; m_c2 = c2; } color_type m_c1; color_type m_c2; }; //======================================================================== template<> struct gradient_linear_color { typedef sgray8 color_type; gradient_linear_color() {} gradient_linear_color(const color_type& c1, const color_type& c2) : m_c1(c1), m_c2(c2) {} static unsigned size() { return 256; } color_type operator [] (unsigned v) const { color_type c; c.v = (int8u)((((m_c2.v - m_c1.v) * int(v)) + (m_c1.v << 8)) >> 8); c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); return c; } void colors(const color_type& c1, const color_type& c2) { m_c1 = c1; m_c2 = c2; } color_type m_c1; color_type m_c2; }; } class the_application : public agg::platform_support { agg::slider_ctrl m_num_cb; public: the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), m_num_cb(5, 5, 150, 12, !flip_y) { parse_lion(); add_ctrl(m_num_cb); m_num_cb.range(2, 10); //m_num_cb.num_steps(8); m_num_cb.label("N=%.2f"); m_num_cb.no_transform(); } virtual void on_draw() { unsigned i; int width = rbuf_window().width(); int height = rbuf_window().height(); pixfmt pf(rbuf_window()); typedef agg::renderer_mclip base_ren_type; base_ren_type r(pf); agg::renderer_scanline_aa_solid rs(r); agg::trans_affine mtx; mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); mtx *= agg::trans_affine_scaling(g_scale, g_scale); mtx *= agg::trans_affine_rotation(g_angle + agg::pi); mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); mtx *= agg::trans_affine_translation(width/2, height/2); r.clear(agg::rgba(1, 1, 1)); r.reset_clipping(false); // Visibility: "false" means "no visible regions" int x, y; double n = m_num_cb.value(); for(x = 0; x < n; x++) { for(y = 0; y < n; y++) { int x1 = int(width * x / n); int y1 = int(height * y / n); int x2 = int(width * (x + 1) / n); int y2 = int(height * (y + 1) / n); r.add_clip_box(x1 + 5, y1 + 5, x2 - 5, y2 - 5); } } // Render the lion agg::conv_transform trans(g_path, mtx); agg::render_all_paths(g_rasterizer, g_scanline, rs, trans, g_colors, g_path_idx, g_npaths); // The scanline rasterizer allows you to perform clipping to multiple // regions "manually", like in the following code, but the "embedded" method // shows much better performance. // //for(i = 0; i < g_npaths; i++) //{ // g_rasterizer.reset(); // g_rasterizer.add_path(trans, g_path_idx[i]); // rs.color(g_colors[i]); // // int x, y; // double n = m_num_cb.value(); // for(x = 0; x < n; x++) // { // for(y = 0; y < n; y++) // { // int x1 = int(width * x / n); // int y1 = int(height * y / n); // int x2 = int(width * (x + 1) / n); // int y2 = int(height * (y + 1) / n); // // r should be of type renderer_base<> // r.clip_box(agg::rect_i(x1 + 5, y1 + 5, x2 - 5, y2 - 5)); // agg::render_scanlines(g_rasterizer, g_scanline, rs); // } // } //} // Render random Bresenham lines and markers agg::renderer_markers m(r); for(i = 0; i < 50; i++) { m.line_color(agg::srgba8(rand() & 0x7F, rand() & 0x7F, rand() & 0x7F, (rand() & 0x7F) + 0x7F)); m.fill_color(agg::srgba8(rand() & 0x7F, rand() & 0x7F, rand() & 0x7F, (rand() & 0x7F) + 0x7F)); m.line(m.coord(rand() % width), m.coord(rand() % height), m.coord(rand() % width), m.coord(rand() % height)); m.marker(rand() % width, rand() % height, rand() % 10 + 5, agg::marker_e(rand() % agg::end_of_markers)); } // Render random anti-aliased lines double w = 5.0; agg::line_profile_aa profile; profile.width(w); typedef agg::renderer_outline_aa renderer_type; renderer_type ren(r, profile); typedef agg::rasterizer_outline_aa rasterizer_type; rasterizer_type ras(ren); ras.round_cap(true); for(i = 0; i < 50; i++) { ren.color(agg::srgba8(rand() & 0x7F, rand() & 0x7F, rand() & 0x7F, (rand() & 0x7F) + 0x7F)); ras.move_to_d(rand() % width, rand() % height); ras.line_to_d(rand() % width, rand() % height); ras.render(false); } // Render random circles with gradient typedef agg::gradient_linear_color grad_color; typedef agg::gradient_circle grad_func; typedef agg::span_interpolator_linear<> interpolator_type; typedef agg::span_gradient span_grad_type; agg::trans_affine grm; grad_func grf; grad_color grc(agg::srgba8(0,0,0), agg::srgba8(0,0,0)); agg::ellipse ell; agg::span_allocator sa; interpolator_type inter(grm); span_grad_type sg(inter, grf, grc, 0, 10); for(i = 0; i < 50; i++) { x = rand() % width; y = rand() % height; double radius = rand() % 10 + 5; grm.reset(); grm *= agg::trans_affine_scaling(radius / 10.0); grm *= agg::trans_affine_translation(x, y); grm.invert(); grc.colors(agg::srgba8(255, 255, 255, 0), agg::srgba8(rand() & 0x7F, rand() & 0x7F, rand() & 0x7F, 255)); sg.color_function(grc); ell.init(x, y, radius, radius, 32); g_rasterizer.add_path(ell); agg::render_scanlines_aa(g_rasterizer, g_scanline, r, sa, sg); } r.reset_clipping(true); // "true" means "all rendering buffer is visible". agg::render_ctrl(g_rasterizer, g_scanline, r, m_num_cb); } void transform(double width, double height, double x, double y) { x -= width / 2; y -= height / 2; g_angle = atan2(y, x); g_scale = sqrt(y * y + x * x) / 100.0; } virtual void on_mouse_button_down(int x, int y, unsigned flags) { if(flags & agg::mouse_left) { int width = rbuf_window().width(); int height = rbuf_window().height(); transform(width, height, x, y); force_redraw(); } if(flags & agg::mouse_right) { g_skew_x = x; g_skew_y = y; force_redraw(); } } virtual void on_mouse_move(int x, int y, unsigned flags) { on_mouse_button_down(x, y, flags); } }; int agg_main(int argc, char* argv[]) { the_application app(pix_format, flip_y); app.caption("AGG Example. Clipping to multiple rectangle regions"); if(app.init(512, 400, agg::window_resize)) { return app.run(); } return 1; }