void draw_polyline(Rasterizer& ras, Renderer& ren, const double* polyline, int num_points) { agg::poly_plain_adaptor<double> vs(polyline, num_points, m_line1.close()); agg::conv_transform<agg::poly_plain_adaptor<double> > trans(vs, m_scale); ras.add_path(trans); }
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); }
the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), m_method (10.0, 10.0, 130.0, 55.0, !flip_y), m_radius (130 + 10.0, 10.0 + 4.0, 130 + 300.0, 10.0 + 8.0 + 4.0, !flip_y), m_shadow_ctrl(4), m_shape(m_path) { add_ctrl(m_method); m_method.text_size(8); m_method.add_item("Single Color"); m_method.add_item("Color LUT"); m_method.cur_item(1); add_ctrl(m_radius); m_radius.range(0.0, 40.0); m_radius.value(15.0); m_radius.label("Blur Radius=%1.2f"); add_ctrl(m_shadow_ctrl); m_path.remove_all(); m_path.move_to(28.47, 6.45); m_path.curve3(21.58, 1.12, 19.82, 0.29); m_path.curve3(17.19, -0.93, 14.21, -0.93); m_path.curve3(9.57, -0.93, 6.57, 2.25); m_path.curve3(3.56, 5.42, 3.56, 10.60); m_path.curve3(3.56, 13.87, 5.03, 16.26); m_path.curve3(7.03, 19.58, 11.99, 22.51); m_path.curve3(16.94, 25.44, 28.47, 29.64); m_path.line_to(28.47, 31.40); m_path.curve3(28.47, 38.09, 26.34, 40.58); m_path.curve3(24.22, 43.07, 20.17, 43.07); m_path.curve3(17.09, 43.07, 15.28, 41.41); m_path.curve3(13.43, 39.75, 13.43, 37.60); m_path.line_to(13.53, 34.77); m_path.curve3(13.53, 32.52, 12.38, 31.30); m_path.curve3(11.23, 30.08, 9.38, 30.08); m_path.curve3(7.57, 30.08, 6.42, 31.35); m_path.curve3(5.27, 32.62, 5.27, 34.81); m_path.curve3(5.27, 39.01, 9.57, 42.53); m_path.curve3(13.87, 46.04, 21.63, 46.04); m_path.curve3(27.59, 46.04, 31.40, 44.04); m_path.curve3(34.28, 42.53, 35.64, 39.31); m_path.curve3(36.52, 37.21, 36.52, 30.71); m_path.line_to(36.52, 15.53); m_path.curve3(36.52, 9.13, 36.77, 7.69); m_path.curve3(37.01, 6.25, 37.57, 5.76); m_path.curve3(38.13, 5.27, 38.87, 5.27); m_path.curve3(39.65, 5.27, 40.23, 5.62); m_path.curve3(41.26, 6.25, 44.19, 9.18); m_path.line_to(44.19, 6.45); m_path.curve3(38.72, -0.88, 33.74, -0.88); m_path.curve3(31.35, -0.88, 29.93, 0.78); m_path.curve3(28.52, 2.44, 28.47, 6.45); m_path.close_polygon(); m_path.move_to(28.47, 9.62); m_path.line_to(28.47, 26.66); m_path.curve3(21.09, 23.73, 18.95, 22.51); m_path.curve3(15.09, 20.36, 13.43, 18.02); m_path.curve3(11.77, 15.67, 11.77, 12.89); m_path.curve3(11.77, 9.38, 13.87, 7.06); m_path.curve3(15.97, 4.74, 18.70, 4.74); m_path.curve3(22.41, 4.74, 28.47, 9.62); m_path.close_polygon(); agg::trans_affine shape_mtx; shape_mtx *= agg::trans_affine_scaling(4.0); shape_mtx *= agg::trans_affine_translation(150, 100); m_path.transform(shape_mtx); agg::bounding_rect_single(m_shape, 0, &m_shape_bounds.x1, &m_shape_bounds.y1, &m_shape_bounds.x2, &m_shape_bounds.y2); m_shadow_ctrl.xn(0) = m_shape_bounds.x1; m_shadow_ctrl.yn(0) = m_shape_bounds.y1; m_shadow_ctrl.xn(1) = m_shape_bounds.x2; m_shadow_ctrl.yn(1) = m_shape_bounds.y1; m_shadow_ctrl.xn(2) = m_shape_bounds.x2; m_shadow_ctrl.yn(2) = m_shape_bounds.y2; m_shadow_ctrl.xn(3) = m_shape_bounds.x1; m_shadow_ctrl.yn(3) = m_shape_bounds.y2; m_shadow_ctrl.line_color(agg::rgba(0, 0.3, 0.5, 0.3)); m_color_lut.resize(256); unsigned i; const agg::int8u* p = g_gradient_colors; for(i = 0; i < 256; i++) { m_color_lut[i] = agg::rgba8(p[0], p[1], p[2], (i > 63) ? 255 : i * 4);//p[3]); //m_color_lut[i].premultiply(); p += 4; } }
virtual void on_draw() { pixfmt pf(rbuf_window()); renderer_base ren_base(pf); ren_base.clear(agg::rgba(0.5, 0.75, 0.85)); renderer_scanline ren(ren_base); rasterizer_scanline ras; scanline sl; ras.clip_box(0, 0, width(), height()); // Pattern 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. //----------------------------------- pattern_src_brightness_to_alpha_rgba8 p1(rbuf_img(0)); agg::pattern_filter_bilinear_rgba8 fltr; // Filtering functor // 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<agg::pattern_filter_bilinear_rgba8> pattern_type; typedef agg::renderer_base<pixfmt> base_ren_type; typedef agg::renderer_outline_image<base_ren_type, pattern_type> renderer_img_type; typedef agg::rasterizer_outline_aa<renderer_img_type, agg::line_coord_sat> rasterizer_img_type; typedef agg::renderer_outline_aa<base_ren_type> renderer_line_type; typedef agg::rasterizer_outline_aa<renderer_line_type, agg::line_coord_sat> rasterizer_line_type; //-- Create with specifying the source //pattern_type patt(fltr, src); //-- Create uninitialized and set the source pattern_type patt(fltr); patt.create(p1); renderer_img_type ren_img(ren_base, patt); rasterizer_img_type ras_img(ren_img); //-- create uninitialized and set parameters agg::line_profile_aa profile; profile.smoother_width(10.0); //optional profile.width(8.0); //mandatory! renderer_line_type ren_line(ren_base, profile); ren_line.color(agg::rgba8(0,0,127)); //mandatory! rasterizer_line_type ras_line(ren_line); ras_line.round_cap(true); //optional //ras_line.line_join(agg::outline_no_join); //optional // Calculate the dilation value so that, the line caps were // drawn correctly. //--------------- double w2 = 9.0;//p1.height() / 2 + 2; // Set the clip box a bit bigger than you expect. You need it // to draw the clipped line caps correctly. The correct result // is achieved with raster clipping. //------------------------ ren_img.scale_x(m_scale_x.value()); ren_img.start_x(m_start_x.value()); ren_img.clip_box (50-w2, 50-w2, width()-50+w2, height()-50+w2); ren_line.clip_box(50-w2, 50-w2, width()-50+w2, height()-50+w2); // First, draw polyline without raster clipping just to show the idea //------------------------ draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points()); draw_polyline(ras_img, ren_img, m_line1.polygon(), m_line1.num_points()); // Clear the area, almost opaque, but not completely //------------------------ ren_base.blend_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1), 200); // Set the raster clip box and then, draw again. // In reality there shouldn't be two calls above. // It's done only for demonstration //------------------------ ren_base.clip_box((int)50, (int)50, (int)width()-50, (int)height()-50); // This "copy_bar" is also for demonstration only //------------------------ ren_base.copy_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1)); // Finally draw polyline correctly clipped: We use double clipping, // first is vector clipping, with extended clip box, second is raster // clipping with normal clip box. //------------------------ ren_img.scale_x(m_scale_x.value()); ren_img.start_x(m_start_x.value()); draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points()); draw_polyline(ras_img, ren_img, m_line1.polygon(), m_line1.num_points()); // Reset clipping and draw the controls and stuff ren_base.reset_clipping(true); m_line1.line_width(1/m_scale.scale()); m_line1.point_radius(5/m_scale.scale()); agg::render_ctrl(ras, sl, ren_base, m_line1); agg::render_ctrl(ras, sl, ren_base, m_scale_x); agg::render_ctrl(ras, sl, ren_base, m_start_x); char buf[256]; agg::gsv_text t; t.size(10.0); agg::conv_stroke<agg::gsv_text> pt(t); pt.width(1.5); pt.line_cap(agg::round_cap); const double* p = m_line1.polygon(); sprintf(buf, "Len=%.2f", agg::calc_distance(p[0], p[1], p[2], p[3]) * m_scale.scale()); t.start_point(10.0, 30.0); t.text(buf); ras.add_path(pt); ren.color(agg::rgba(0,0,0)); agg::render_scanlines(ras, sl, ren); }
the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), m_ctrl_color(agg::rgba(0, 0.3, 0.5, 0.3)), m_line1(5), m_scale_x(5.0, 5.0, 240.0, 12.0, !flip_y), m_start_x(250.0, 5.0, 495.0, 12.0, !flip_y) { m_line1.line_color(m_ctrl_color); m_line1.xn(0) = 20; m_line1.yn(0) = 20; m_line1.xn(1) = 500-20; m_line1.yn(1) = 500-20; m_line1.xn(2) = 500-60; m_line1.yn(2) = 20; m_line1.xn(3) = 40; m_line1.yn(3) = 500-40; m_line1.xn(4) = 100; m_line1.yn(4) = 300; m_line1.close(false); add_ctrl(m_line1); m_line1.transform(m_scale); m_scale_x.label("Scale X=%.2f"); m_scale_x.range(0.2, 3.0); m_scale_x.value(1.0); add_ctrl(m_scale_x); m_scale_x.no_transform(); m_start_x.label("Start X=%.2f"); m_start_x.range(0.0, 10.0); m_start_x.value(0.0); add_ctrl(m_start_x); m_start_x.no_transform(); }
the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), m_method (10.0, 10.0, 130.0, 70.0, !flip_y), m_radius (130 + 10.0, 10.0 + 4.0, 130 + 300.0, 10.0 + 8.0 + 4.0, !flip_y), m_shadow_ctrl(4), m_channel_r (10.0, 80.0, "Red", !flip_y), m_channel_g (10.0, 95.0, "Green", !flip_y), m_channel_b (10.0, 110.0, "Blue", !flip_y), m_shape(m_path) { add_ctrl(m_method); m_method.text_size(8); m_method.add_item("Stack Blur"); m_method.add_item("Recursive Blur"); m_method.add_item("Channels"); m_method.cur_item(0); add_ctrl(m_radius); m_radius.range(0.0, 40.0); m_radius.value(15.0); m_radius.label("Blur Radius=%1.2f"); add_ctrl(m_shadow_ctrl); add_ctrl(m_channel_r); add_ctrl(m_channel_g); add_ctrl(m_channel_b); m_channel_g.status(true); m_path.remove_all(); m_path.move_to(28.47, 6.45); m_path.curve3(21.58, 1.12, 19.82, 0.29); m_path.curve3(17.19, -0.93, 14.21, -0.93); m_path.curve3(9.57, -0.93, 6.57, 2.25); m_path.curve3(3.56, 5.42, 3.56, 10.60); m_path.curve3(3.56, 13.87, 5.03, 16.26); m_path.curve3(7.03, 19.58, 11.99, 22.51); m_path.curve3(16.94, 25.44, 28.47, 29.64); m_path.line_to(28.47, 31.40); m_path.curve3(28.47, 38.09, 26.34, 40.58); m_path.curve3(24.22, 43.07, 20.17, 43.07); m_path.curve3(17.09, 43.07, 15.28, 41.41); m_path.curve3(13.43, 39.75, 13.43, 37.60); m_path.line_to(13.53, 34.77); m_path.curve3(13.53, 32.52, 12.38, 31.30); m_path.curve3(11.23, 30.08, 9.38, 30.08); m_path.curve3(7.57, 30.08, 6.42, 31.35); m_path.curve3(5.27, 32.62, 5.27, 34.81); m_path.curve3(5.27, 39.01, 9.57, 42.53); m_path.curve3(13.87, 46.04, 21.63, 46.04); m_path.curve3(27.59, 46.04, 31.40, 44.04); m_path.curve3(34.28, 42.53, 35.64, 39.31); m_path.curve3(36.52, 37.21, 36.52, 30.71); m_path.line_to(36.52, 15.53); m_path.curve3(36.52, 9.13, 36.77, 7.69); m_path.curve3(37.01, 6.25, 37.57, 5.76); m_path.curve3(38.13, 5.27, 38.87, 5.27); m_path.curve3(39.65, 5.27, 40.23, 5.62); m_path.curve3(41.26, 6.25, 44.19, 9.18); m_path.line_to(44.19, 6.45); m_path.curve3(38.72, -0.88, 33.74, -0.88); m_path.curve3(31.35, -0.88, 29.93, 0.78); m_path.curve3(28.52, 2.44, 28.47, 6.45); m_path.close_polygon(); m_path.move_to(28.47, 9.62); m_path.line_to(28.47, 26.66); m_path.curve3(21.09, 23.73, 18.95, 22.51); m_path.curve3(15.09, 20.36, 13.43, 18.02); m_path.curve3(11.77, 15.67, 11.77, 12.89); m_path.curve3(11.77, 9.38, 13.87, 7.06); m_path.curve3(15.97, 4.74, 18.70, 4.74); m_path.curve3(22.41, 4.74, 28.47, 9.62); m_path.close_polygon(); agg::trans_affine shape_mtx; shape_mtx *= agg::trans_affine_scaling(4.0); shape_mtx *= agg::trans_affine_translation(150, 100); m_path.transform(shape_mtx); agg::bounding_rect_single(m_shape, 0, &m_shape_bounds.x1, &m_shape_bounds.y1, &m_shape_bounds.x2, &m_shape_bounds.y2); m_shadow_ctrl.xn(0) = m_shape_bounds.x1; m_shadow_ctrl.yn(0) = m_shape_bounds.y1; m_shadow_ctrl.xn(1) = m_shape_bounds.x2; m_shadow_ctrl.yn(1) = m_shape_bounds.y1; m_shadow_ctrl.xn(2) = m_shape_bounds.x2; m_shadow_ctrl.yn(2) = m_shape_bounds.y2; m_shadow_ctrl.xn(3) = m_shape_bounds.x1; m_shadow_ctrl.yn(3) = m_shape_bounds.y2; m_shadow_ctrl.line_color(agg::rgba(0, 0.3, 0.5, 0.3)); }
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); }