virtual void on_draw() { pixfmt pixf(rbuf_window()); renderer_base rb(pixf); renderer_solid r(rb); rb.clear(agg::rgba(1, 1, 1)); g_rasterizer.clip_box(0, 0, width(), height()); if(m_trans_type.cur_item() == 0) { agg::trans_bilinear tr(g_x1, g_y1, g_x2, g_y2, m_quad.polygon()); if(tr.is_valid()) { //-------------------------- // Render transformed lion // agg::conv_transform<agg::path_storage, agg::trans_bilinear> trans(g_path, tr); agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); //-------------------------- //-------------------------- // Render transformed ellipse // agg::ellipse ell((g_x1 + g_x2) * 0.5, (g_y1 + g_y2) * 0.5, (g_x2 - g_x1) * 0.5, (g_y2 - g_y1) * 0.5, 200); agg::conv_stroke<agg::ellipse> ell_stroke(ell); ell_stroke.width(3.0); agg::conv_transform<agg::ellipse, agg::trans_bilinear> trans_ell(ell, tr); agg::conv_transform<agg::conv_stroke<agg::ellipse>, agg::trans_bilinear> trans_ell_stroke(ell_stroke, tr); g_rasterizer.add_path(trans_ell); r.color(agg::rgba(0.5, 0.3, 0.0, 0.3)); agg::render_scanlines(g_rasterizer, g_scanline, r); g_rasterizer.add_path(trans_ell_stroke); r.color(agg::rgba(0.0, 0.3, 0.2, 1.0)); agg::render_scanlines(g_rasterizer, g_scanline, r); //-------------------------- } } else { agg::trans_perspective tr(g_x1, g_y1, g_x2, g_y2, m_quad.polygon()); if(tr.is_valid()) { //-------------------------- // Render transformed lion // agg::conv_transform<agg::path_storage, agg::trans_perspective> trans(g_path, tr); agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); //-------------------------- //-------------------------- // Render transformed ellipse // agg::ellipse ell((g_x1 + g_x2) * 0.5, (g_y1 + g_y2) * 0.5, (g_x2 - g_x1) * 0.5, (g_y2 - g_y1) * 0.5, 200); agg::conv_stroke<agg::ellipse> ell_stroke(ell); ell_stroke.width(3.0); agg::conv_transform<agg::ellipse, agg::trans_perspective> trans_ell(ell, tr); agg::conv_transform<agg::conv_stroke<agg::ellipse>, agg::trans_perspective> trans_ell_stroke(ell_stroke, tr); g_rasterizer.add_path(trans_ell); r.color(agg::rgba(0.5, 0.3, 0.0, 0.3)); agg::render_scanlines(g_rasterizer, g_scanline, r); g_rasterizer.add_path(trans_ell_stroke); r.color(agg::rgba(0.0, 0.3, 0.2, 1.0)); agg::render_scanlines(g_rasterizer, g_scanline, r); //-------------------------- // Testing the reverse transformations //agg::trans_perspective tr2(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); //if(tr2.is_valid()) //{ // double x, y; // x = m_quad.xn(0); y = m_quad.yn(0); tr2.transform(&x, &y); // g_rasterizer.move_to_d(x, y); // x = m_quad.xn(1); y = m_quad.yn(1); tr2.transform(&x, &y); // g_rasterizer.line_to_d(x, y); // x = m_quad.xn(2); y = m_quad.yn(2); tr2.transform(&x, &y); // g_rasterizer.line_to_d(x, y); // x = m_quad.xn(3); y = m_quad.yn(3); tr2.transform(&x, &y); // g_rasterizer.line_to_d(x, y); // r.color(agg::rgba(0.5, 0.0, 0.0, 0.5)); // agg::render_scanlines(g_rasterizer, g_scanline, r); //} //else //{ // message("Singularity..."); //} } } //-------------------------- // Render the "quad" tool and controls g_rasterizer.add_path(m_quad); r.color(agg::rgba(0, 0.3, 0.5, 0.6)); agg::render_scanlines(g_rasterizer, g_scanline, r); agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); //-------------------------- }
virtual void on_draw() { pixfmt pixf(rbuf_window()); pixfmt_pre pixf_pre(rbuf_window()); renderer_base rb(pixf); renderer_base_pre rb_pre(pixf_pre); if(!m_test_flag) { rb.clear(agg::rgba(1, 1, 1)); } if(m_trans_type.cur_item() == 0) { // For the affine parallelogram transformations we // calculate the 4-th (implicit) point of the parallelogram m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); } if(!m_test_flag) { //-------------------------- // Render the "quad" tool and controls g_rasterizer.add_path(m_quad); agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, agg::rgba(0, 0.3, 0.5, 0.6)); //-------------------------- agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); } // Prepare the polygon to rasterize. Here we need to fill // the destination (transformed) polygon. g_rasterizer.clip_box(0, 0, width(), height()); g_rasterizer.reset(); g_rasterizer.move_to_d(m_quad.xn(0), m_quad.yn(0)); g_rasterizer.line_to_d(m_quad.xn(1), m_quad.yn(1)); g_rasterizer.line_to_d(m_quad.xn(2), m_quad.yn(2)); g_rasterizer.line_to_d(m_quad.xn(3), m_quad.yn(3)); typedef agg::span_allocator<color_type> span_alloc_type; span_alloc_type sa; agg::image_filter<agg::image_filter_hanning> filter; typedef agg::wrap_mode_reflect_auto_pow2 remainder_type; typedef agg::image_accessor_wrap<pixfmt, remainder_type, remainder_type> img_source_type; pixfmt img_pixf(rbuf_img(0)); img_source_type img_src(img_pixf); enum subdiv_shift_e { subdiv_shift = 2 }; switch(m_trans_type.cur_item()) { case 0: { // Note that we consruct an affine matrix that transforms // a parallelogram to a rectangle, i.e., it's inverted. // It's actually the same as: // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon()); // tr.invert(); agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); // Also note that we can use the linear interpolator instead of // arbitrary span_interpolator_trans. It works much faster, // but the transformations must be linear and parellel. typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type; interpolator_type interpolator(tr); typedef span_image_filter_2x2<img_source_type, interpolator_type> span_gen_type; span_gen_type sg(img_src, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); break; } case 1: { agg::trans_bilinear tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); if(tr.is_valid()) { typedef agg::span_interpolator_linear<agg::trans_bilinear> interpolator_type; interpolator_type interpolator(tr); typedef span_image_filter_2x2<img_source_type, interpolator_type> span_gen_type; span_gen_type sg(img_src, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } case 2: { agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); if(tr.is_valid()) { typedef agg::span_interpolator_linear_subdiv<agg::trans_perspective, 8> interpolator_type; interpolator_type interpolator(tr); typedef span_image_filter_2x2<img_source_type, interpolator_type> span_gen_type; span_gen_type sg(img_src, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } } }
void roadmap_canvas_agg_configure (unsigned char *buf, int width, int height, int stride) { roadmap_log( ROADMAP_ERROR, "roadmap_canvas_agg_configure, height =%d width=%d",height, width); agg_rbuf.attach(buf, width, height, stride); agg_renb.attach(agg_pixf); agg_renb.reset_clipping(true); ras.clip_box(0, 0, agg_renb.width() - 1, agg_renb.height() - 1); agg::glyph_rendering gren = agg::glyph_ren_outline; agg::glyph_rendering image_gren = agg::glyph_ren_agg_gray8; roadmap_config_declare ("preferences", &RoadMapConfigFont, "font.ttf", NULL); roadmap_config_declare ("preferences", &RoadMapConfigFontNormal, "font_normal.ttf", NULL); char *font_file = roadmap_path_join(roadmap_path_user(), roadmap_config_get (&RoadMapConfigFont)); if ((width) && (height)) roadmap_screen_set_screen_type( width, height ); if (!RoadMapCanvasFontLoaded) { if(m_feng.load_font(font_file, 0, gren) && m_image_feng.load_font(font_file, 0, image_gren)) { m_feng.hinting(true); if ( roadmap_screen_is_hd_screen() ) { m_feng.height(22); m_feng.width(22); } else { #ifdef _WIN32 m_feng.height(12); m_feng.width(12); #else m_feng.height(15); m_feng.width(15); #endif } m_feng.flip_y(true); m_image_feng.hinting(true); m_image_feng.flip_y(true); RoadMapCanvasFontLoaded = 1; } else { RoadMapCanvasFontLoaded = -1; char message[300]; snprintf(message, sizeof(message), "Can't load font: %s\n", font_file); roadmap_messagebox("Error", message); } } RoadMapCanvasFontLoaded = 1; roadmap_path_free(font_file); font_file = roadmap_path_join(roadmap_path_user(), roadmap_config_get (&RoadMapConfigFontNormal)); if(m_feng_nor.load_font(font_file, 0, gren) && m_image_feng_nor.load_font(font_file, 0, image_gren)) { m_feng_nor.hinting(true); if ( roadmap_screen_is_hd_screen() ) { m_feng_nor.height(22); m_feng_nor.width(22); } else { #ifdef _WIN32 m_feng_nor.height(12); m_feng_nor.width(12); #else m_feng_nor.height(15); m_feng_nor.width(15); #endif } m_feng_nor.flip_y(true); m_image_feng_nor.hinting(true); m_image_feng_nor.flip_y(true); RoadMapCanvasNormalFontLoaded = 1; } }
virtual void on_draw() { if(m_gamma.value() != m_old_gamma) { m_gamma_lut.gamma(m_gamma.value()); load_img(0, "spheres"); pixfmt pixf(rbuf_img(0)); pixf.apply_gamma_dir(m_gamma_lut); m_old_gamma = m_gamma.value(); } pixfmt pixf(rbuf_window()); pixfmt_pre pixf_pre(rbuf_window()); renderer_base rb(pixf); renderer_base_pre rb_pre(pixf_pre); renderer_solid r(rb); rb.clear(agg::rgba(1, 1, 1)); if(m_trans_type.cur_item() < 2) { // For the affine parallelogram transformations we // calculate the 4-th (implicit) point of the parallelogram m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); } //-------------------------- // Render the "quad" tool and controls g_rasterizer.add_path(m_quad); r.color(agg::rgba(0, 0.3, 0.5, 0.1)); agg::render_scanlines(g_rasterizer, g_scanline, r); // Prepare the polygon to rasterize. Here we need to fill // the destination (transformed) polygon. g_rasterizer.clip_box(0, 0, width(), height()); g_rasterizer.reset(); int b = 0; g_rasterizer.move_to_d(m_quad.xn(0)-b, m_quad.yn(0)-b); g_rasterizer.line_to_d(m_quad.xn(1)+b, m_quad.yn(1)-b); g_rasterizer.line_to_d(m_quad.xn(2)+b, m_quad.yn(2)+b); g_rasterizer.line_to_d(m_quad.xn(3)-b, m_quad.yn(3)+b); typedef agg::span_allocator<color_type> span_alloc_type; span_alloc_type sa; agg::image_filter_bilinear filter_kernel; agg::image_filter_lut filter(filter_kernel, true); pixfmt pixf_img(rbuf_img(0)); typedef agg::image_accessor_clone<pixfmt> source_type; source_type source(pixf_img); start_timer(); switch(m_trans_type.cur_item()) { case 0: { agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type; interpolator_type interpolator(tr); typedef image_filter_2x2_type<source_type, interpolator_type> span_gen_type; span_gen_type sg(source, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); break; } case 1: { agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type; typedef image_resample_affine_type<source_type> span_gen_type; interpolator_type interpolator(tr); span_gen_type sg(source, interpolator, filter); sg.blur(m_blur.value()); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); break; } case 2: { agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); if(tr.is_valid()) { typedef agg::span_interpolator_linear_subdiv<agg::trans_perspective> interpolator_type; interpolator_type interpolator(tr); typedef image_filter_2x2_type<source_type, interpolator_type> span_gen_type; span_gen_type sg(source, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } case 3: { agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); if(tr.is_valid()) { typedef agg::span_interpolator_trans<agg::trans_perspective> interpolator_type; interpolator_type interpolator(tr); typedef image_filter_2x2_type<source_type, interpolator_type> span_gen_type; span_gen_type sg(source, interpolator, filter); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } case 4: { typedef agg::span_interpolator_persp_lerp<> interpolator_type; typedef agg::span_subdiv_adaptor<interpolator_type> subdiv_adaptor_type; interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); subdiv_adaptor_type subdiv_adaptor(interpolator); if(interpolator.is_valid()) { typedef image_resample_type<source_type, subdiv_adaptor_type> span_gen_type; span_gen_type sg(source, subdiv_adaptor, filter); sg.blur(m_blur.value()); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } case 5: { typedef agg::span_interpolator_persp_exact<> interpolator_type; typedef agg::span_subdiv_adaptor<interpolator_type> subdiv_adaptor_type; interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); subdiv_adaptor_type subdiv_adaptor(interpolator); if(interpolator.is_valid()) { typedef image_resample_type<source_type, subdiv_adaptor_type> span_gen_type; span_gen_type sg(source, subdiv_adaptor, filter); sg.blur(m_blur.value()); agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); } break; } } double tm = elapsed_time(); pixf.apply_gamma_inv(m_gamma_lut); char buf[64]; agg::gsv_text t; t.size(10.0); agg::conv_stroke<agg::gsv_text> pt(t); pt.width(1.5); sprintf(buf, "%3.2f ms", tm); t.start_point(10.0, 70.0); t.text(buf); g_rasterizer.add_path(pt); r.color(agg::rgba(0,0,0)); agg::render_scanlines(g_rasterizer, g_scanline, r); //-------------------------- agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); agg::render_ctrl(g_rasterizer, g_scanline, rb, m_gamma); agg::render_ctrl(g_rasterizer, g_scanline, rb, m_blur); }
virtual void on_draw() { typedef agg::pixfmt_gray8 pixfmt_gray8; typedef agg::renderer_base<pixfmt_gray8> ren_base_gray8; m_ras.clip_box(0,0, width(), height()); pixfmt_gray8 pixf_gray8(m_gray8_rbuf); ren_base_gray8 renb_gray8(pixf_gray8); renb_gray8.clear(agg::gray8(0)); // Testing enhanced compositing operations. // Uncomment and replace renb.blend_from_* to renb_blend.blend_from_* //---------------- //typedef agg::comp_op_rgba_minus<color_type, component_order> blender_type; //typedef agg::comp_adaptor_rgba<blender_type> blend_adaptor_type; //typedef agg::pixfmt_custom_blend_rgba<blend_adaptor_type, agg::rendering_buffer> pixfmt_type; //typedef agg::renderer_base<pixfmt_type> ren_base; //pixfmt_type pixf_blend(rbuf_window()); //agg::renderer_base<pixfmt_type> renb_blend(pixf_blend); pixfmt pixf(rbuf_window()); agg::renderer_base<pixfmt> renb(pixf); renb.clear(agg::rgba(1, 0.95, 0.95)); agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, m_shape_bounds.x2, m_shape_bounds.y2, m_shadow_ctrl.polygon()); agg::conv_transform<shape_type, agg::trans_perspective> shadow_trans(m_shape, shadow_persp); start_timer(); // Render shadow m_ras.add_path(shadow_trans); agg::render_scanlines_aa_solid(m_ras, m_sl, renb_gray8, agg::gray8(255)); // Calculate the bounding box and extend it by the blur radius agg::rect_d bbox; agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2); bbox.x1 -= m_radius.value(); bbox.y1 -= m_radius.value(); bbox.x2 += m_radius.value(); bbox.y2 += m_radius.value(); if(bbox.clip(agg::rect_d(0, 0, width(), height()))) { // Create a new pixel renderer and attach it to the main one as a child image. // It returns true if the attachment suceeded. It fails if the rectangle // (bbox) is fully clipped. //------------------ pixfmt_gray8 pixf2(m_gray8_rbuf2); if(pixf2.attach(pixf_gray8, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { // Blur it agg::stack_blur_gray8(pixf2, agg::uround(m_radius.value()), agg::uround(m_radius.value())); } if(m_method.cur_item() == 0) { renb.blend_from_color(pixf2, agg::rgba8(0, 100, 0), 0, int(bbox.x1), int(bbox.y1)); } else { renb.blend_from_lut(pixf2, m_color_lut.data(), 0, int(bbox.x1), int(bbox.y1)); } } double tm = elapsed_time(); char buf[64]; agg::gsv_text t; t.size(10.0); agg::conv_stroke<agg::gsv_text> st(t); st.width(1.5); sprintf(buf, "%3.2f ms", tm); t.start_point(140.0, 30.0); t.text(buf); m_ras.add_path(st); agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0)); agg::render_ctrl(m_ras, m_sl, renb, m_method); agg::render_ctrl(m_ras, m_sl, renb, m_radius); agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl); }
virtual void on_draw() { typedef agg::renderer_base<agg::pixfmt_bgr24> ren_base; agg::pixfmt_bgr24 pixf(rbuf_window()); ren_base renb(pixf); renb.clear(agg::rgba(1, 1, 1)); m_ras.clip_box(0,0, width(), height()); agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, m_shape_bounds.x2, m_shape_bounds.y2, m_shadow_ctrl.polygon()); agg::conv_transform<shape_type, agg::trans_perspective> shadow_trans(m_shape, shadow_persp); // Render shadow m_ras.add_path(shadow_trans); agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.2,0.3,0)); // Calculate the bounding box and extend it by the blur radius agg::rect_d bbox; agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2); bbox.x1 -= m_radius.value(); bbox.y1 -= m_radius.value(); bbox.x2 += m_radius.value(); bbox.y2 += m_radius.value(); if(m_method.cur_item() == 1) { // The recursive blur method represents the true Gussian Blur, // with theoretically infinite kernel. The restricted window size // results in extra influence of edge pixels. It's impossible to // solve correctly, but extending the right and top areas to another // radius value produces fair result. //------------------ bbox.x2 += m_radius.value(); bbox.y2 += m_radius.value(); } start_timer(); if(m_method.cur_item() != 2) { // Create a new pixel renderer and attach it to the main one as a child image. // It returns true if the attachment suceeded. It fails if the rectangle // (bbox) is fully clipped. //------------------ agg::pixfmt_bgr24 pixf2(m_rbuf2); if(pixf2.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { // Blur it if(m_method.cur_item() == 0) { // More general method, but 30-40% slower. //------------------ //m_stack_blur.blur(pixf2, agg::uround(m_radius.value())); // Faster, but bore specific. // Works only for 8 bits per channel and only with radii <= 254. //------------------ agg::stack_blur_rgb24(pixf2, agg::uround(m_radius.value()), agg::uround(m_radius.value())); } else { // True Gaussian Blur, 3-5 times slower than Stack Blur, // but still constant time of radius. Very sensitive // to precision, doubles are must here. //------------------ m_recursive_blur.blur(pixf2, m_radius.value()); } } } else { // Blur separate channels //------------------ if(m_channel_r.status()) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 2> pixfmt_gray8r; pixfmt_gray8r pixf2r(m_rbuf2); if(pixf2r.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2r, agg::uround(m_radius.value()), agg::uround(m_radius.value())); } } if(m_channel_g.status()) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 1> pixfmt_gray8g; pixfmt_gray8g pixf2g(m_rbuf2); if(pixf2g.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2g, agg::uround(m_radius.value()), agg::uround(m_radius.value())); } } if(m_channel_b.status()) { typedef agg::pixfmt_alpha_blend_gray< agg::blender_gray8, agg::rendering_buffer, 3, 0> pixfmt_gray8b; pixfmt_gray8b pixf2b(m_rbuf2); if(pixf2b.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) { agg::stack_blur_gray8(pixf2b, agg::uround(m_radius.value()), agg::uround(m_radius.value())); } } } double tm = elapsed_time(); agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl); // Render the shape itself //------------------ m_ras.add_path(m_shape); agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.6,0.9,0.7, 0.8)); char buf[64]; agg::gsv_text t; t.size(10.0); agg::conv_stroke<agg::gsv_text> st(t); st.width(1.5); sprintf(buf, "%3.2f ms", tm); t.start_point(140.0, 30.0); t.text(buf); m_ras.add_path(st); agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0)); agg::render_ctrl(m_ras, m_sl, renb, m_method); agg::render_ctrl(m_ras, m_sl, renb, m_radius); agg::render_ctrl(m_ras, m_sl, renb, m_channel_r); agg::render_ctrl(m_ras, m_sl, renb, m_channel_g); agg::render_ctrl(m_ras, m_sl, renb, m_channel_b); }