Exemple #1
0
        public override void OnDraw(Graphics2D graphics2D)
        {
            ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());

            int width  = (int)widgetsSubImage.Width;
            int height = (int)widgetsSubImage.Height;

            ImageBuffer clippedSubImage = new ImageBuffer();

            clippedSubImage.Attach(widgetsSubImage, new BlenderBGRA());
            ImageClippingProxy imageClippingProxy = new ImageClippingProxy(clippedSubImage);

            imageClippingProxy.clear(new ColorF(1, 1, 1));

            Affine transform = Affine.NewIdentity();

            transform *= Affine.NewTranslation(-lionShape.Center.X, -lionShape.Center.Y);
            transform *= Affine.NewScaling(lionScale, lionScale);
            transform *= Affine.NewRotation(angle + Math.PI);
            transform *= Affine.NewSkewing(skewX / 1000.0, skewY / 1000.0);
            transform *= Affine.NewTranslation(width / 2, height / 2);

            if (renderAsScanlineCheckBox.Checked)
            {
                rasterizer.SetVectorClipBox(0, 0, width, height);

                foreach (var shape in lionShape.Shapes)
                {
                    Stroke stroke = new Stroke(shape.VertexStorage);
                    stroke.Width    = widthSlider.Value;
                    stroke.LineJoin = LineJoin.Round;
                    VertexSourceApplyTransform trans            = new VertexSourceApplyTransform(stroke, transform);
                    ScanlineRenderer           scanlineRenderer = new ScanlineRenderer();
                    rasterizer.add_path(trans);
                    scanlineRenderer.RenderSolid(imageClippingProxy, rasterizer, scanlineCache, shape.Color);
                }
            }
            else
            {
                double w = widthSlider.Value * transform.GetScale();

                LineProfileAnitAlias  lineProfile     = new LineProfileAnitAlias(w, new gamma_none());
                OutlineRenderer       outlineRenderer = new OutlineRenderer(imageClippingProxy, lineProfile);
                rasterizer_outline_aa rasterizer      = new rasterizer_outline_aa(outlineRenderer);

                rasterizer.line_join(renderAccurateJoinsCheckBox.Checked ?
                                     rasterizer_outline_aa.outline_aa_join_e.outline_miter_accurate_join
                                        : rasterizer_outline_aa.outline_aa_join_e.outline_round_join);
                rasterizer.round_cap(true);

                foreach (var shape in lionShape.Shapes)
                {
                    VertexSourceApplyTransform trans = new VertexSourceApplyTransform(shape.VertexStorage, transform);
                    rasterizer.RenderAllPaths(trans, new Color[] { shape.Color }, new int[] { 0 }, 1);
                }
            }

            base.OnDraw(graphics2D);
        }
Exemple #2
0
		private void DrawBigA(Graphics2D graphics2D)
		{
			ScanlineRasterizer m_ras = new ScanlineRasterizer();
			m_ras.SetVectorClipBox(0, 0, Width, Height);
			TypeFacePrinter bigAPrinter = new TypeFacePrinter("a", 150);
			FlattenCurves flattenedBigA = new FlattenCurves(bigAPrinter);
			VertexSourceApplyTransform scaleAndTranslate = new VertexSourceApplyTransform(flattenedBigA, Affine.NewTranslation(155, 55));
			ScanlineCachePacked8 m_sl = new ScanlineCachePacked8();
			ScanlineRenderer scanlineRenderer = new ScanlineRenderer();

#if false
            ImageProxySubpxelLcd24 clippingProxy = new ImageProxySubpxelLcd24(graphics2D.DestImage, new lcd_distribution_lut());
            VertexSourceApplyTransform scaledWide = new VertexSourceApplyTransform(scaleAndTranslate, Affine.NewScaling(3, 1));
            m_ras.add_path(scaledWide);
            scanlineRenderer.render_scanlines_aa_solid(clippingProxy, m_ras, m_sl, RGBA_Bytes.Black);
#else
			m_ras.add_path(scaleAndTranslate);
			ImageClippingProxy clippingProxy = new ImageClippingProxy(graphics2D.DestImage);
			scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, RGBA_Bytes.Black);
#endif
		}
        private void DrawBigA(Graphics2D graphics2D)
        {
            ScanlineRasterizer m_ras = new ScanlineRasterizer();

            m_ras.SetVectorClipBox(0, 0, Width, Height);
            TypeFacePrinter            bigAPrinter       = new TypeFacePrinter("a", 150);
            FlattenCurves              flattenedBigA     = new FlattenCurves(bigAPrinter);
            VertexSourceApplyTransform scaleAndTranslate = new VertexSourceApplyTransform(flattenedBigA, Affine.NewTranslation(155, 55));
            ScanlineCachePacked8       m_sl             = new ScanlineCachePacked8();
            ScanlineRenderer           scanlineRenderer = new ScanlineRenderer();

#if false
            ImageProxySubpxelLcd24     clippingProxy = new ImageProxySubpxelLcd24(graphics2D.DestImage, new lcd_distribution_lut());
            VertexSourceApplyTransform scaledWide    = new VertexSourceApplyTransform(scaleAndTranslate, Affine.NewScaling(3, 1));
            m_ras.add_path(scaledWide);
            scanlineRenderer.render_scanlines_aa_solid(clippingProxy, m_ras, m_sl, RGBA_Bytes.Black);
#else
            m_ras.add_path(scaleAndTranslate);
            ImageClippingProxy clippingProxy = new ImageClippingProxy(graphics2D.DestImage);
            scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, RGBA_Bytes.Black);
#endif
        }
Exemple #4
0
        public override void OnDraw(Graphics2D graphics2D)
        {
            ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());

            if (!didInit)
            {
                didInit = true;
                OnInitialize();
            }

            if (m_gamma.Value != m_old_gamma)
            {
                m_gamma_lut.SetGamma(m_gamma.Value);
                ImageIO.LoadImageData("spheres.bmp", m_SourceImage);
                //m_SourceImage.apply_gamma_dir(m_gamma_lut);
                m_old_gamma = m_gamma.Value;
            }

            ImageBuffer pixf = new ImageBuffer();

            switch (widgetsSubImage.BitDepth)
            {
            case 24:
                pixf.Attach(widgetsSubImage, new BlenderBGR());
                break;

            case 32:
                pixf.Attach(widgetsSubImage, new BlenderBGRA());
                break;

            default:
                throw new NotImplementedException();
            }

            ImageClippingProxy clippingProxy = new ImageClippingProxy(pixf);

            clippingProxy.clear(new ColorF(1, 1, 1));

            if (m_trans_type.SelectedIndex < 2)
            {
                // For the affine parallelogram transformations we
                // calculate the 4-th (implicit) point of the parallelogram
                m_quad.SetXN(3, m_quad.GetXN(0) + (m_quad.GetXN(2) - m_quad.GetXN(1)));
                m_quad.SetYN(3, m_quad.GetYN(0) + (m_quad.GetYN(2) - m_quad.GetYN(1)));
            }

            ScanlineRenderer scanlineRenderer = new ScanlineRenderer();
            // draw a background to show how the alpha is working
            int RectWidth = 70;
            int xoffset   = 50;
            int yoffset   = 50;

            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 7; j++)
                {
                    if ((i + j) % 2 != 0)
                    {
                        VertexSource.RoundedRect rect = new VertexSource.RoundedRect(i * RectWidth + xoffset, j * RectWidth + yoffset,
                                                                                     (i + 1) * RectWidth + xoffset, (j + 1) * RectWidth + yoffset, 2);
                        rect.normalize_radius();

                        g_rasterizer.add_path(rect);
                        scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new Color(.2, .2, .2));
                    }
                }
            }

            //--------------------------
            // Render the "quad" tool and controls
            g_rasterizer.add_path(m_quad);
            scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new Color(0, 0.3, 0.5, 0.1));

            // Prepare the polygon to rasterize. Here we need to fill
            // the destination (transformed) polygon.
            g_rasterizer.SetVectorClipBox(0, 0, Width, Height);
            g_rasterizer.reset();
            int b = 0;

            g_rasterizer.move_to_d(m_quad.GetXN(0) - b, m_quad.GetYN(0) - b);
            g_rasterizer.line_to_d(m_quad.GetXN(1) + b, m_quad.GetYN(1) - b);
            g_rasterizer.line_to_d(m_quad.GetXN(2) + b, m_quad.GetYN(2) + b);
            g_rasterizer.line_to_d(m_quad.GetXN(3) - b, m_quad.GetYN(3) + b);

            //typedef agg::span_allocator<color_type> span_alloc_type;
            span_allocator         sa            = new span_allocator();
            image_filter_bilinear  filter_kernel = new image_filter_bilinear();
            ImageFilterLookUpTable filter        = new ImageFilterLookUpTable(filter_kernel, true);

            ImageBufferAccessorClamp source = new ImageBufferAccessorClamp(m_SourceImage);

            stopwatch.Restart();

            switch (m_trans_type.SelectedIndex)
            {
            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;

                span_interpolator_persp_lerp interpolator   = new span_interpolator_persp_lerp(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
                span_subdiv_adaptor          subdiv_adaptor = new span_subdiv_adaptor(interpolator);

                span_image_resample sg = null;
                if (interpolator.is_valid())
                {
                    switch (source.SourceImage.BitDepth)
                    {
                    case 24:
                        sg = new span_image_resample_rgb(source, subdiv_adaptor, filter);
                        break;

                    case 32:
                        sg = new span_image_resample_rgba(source, subdiv_adaptor, filter);
                        break;
                    }

                    sg.blur(m_blur.Value);
                    scanlineRenderer.GenerateAndRender(g_rasterizer, g_scanline, clippingProxy, 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 = stopwatch.ElapsedMilliseconds;
            //pixf.apply_gamma_inv(m_gamma_lut);

            gsv_text t = new gsv_text();

            t.SetFontSize(10.0);

            Stroke pt = new Stroke(t);

            pt.Width = 1.5;

            string buf = string.Format("{0:F2} ms", tm);

            t.start_point(10.0, 70.0);
            t.text(buf);

            g_rasterizer.add_path(pt);
            scanlineRenderer.RenderSolid(clippingProxy, g_rasterizer, g_scanline, new Color(0, 0, 0));

            //--------------------------
            //m_trans_type.Render(g_rasterizer, g_scanline, clippingProxy);
            //m_gamma.Render(g_rasterizer, g_scanline, clippingProxy);
            //m_blur.Render(g_rasterizer, g_scanline, clippingProxy);
            base.OnDraw(graphics2D);
        }
Exemple #5
0
        public override void OnDraw(Graphics2D graphics2D)
        {
            ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());

            if (orignialSize.x == 0)
            {
                orignialSize.x = WindowSize.x;
                orignialSize.y = WindowSize.y;
            }

            ImageBuffer destImageWithPreMultBlender = new ImageBuffer();

            switch (widgetsSubImage.BitDepth)
            {
            case 24:
                destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGR());
                break;

            case 32:
                destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGRA());
                break;

            default:
                throw new Exception("Unknown bit depth");
            }

            ImageClippingProxy clippingProxy_pre = new ImageClippingProxy(destImageWithPreMultBlender);

            clippingProxy_pre.clear(new RGBA_Floats(1.0, 1.0, 1.0));

            Affine src_mtx = Affine.NewIdentity();

            src_mtx *= Affine.NewTranslation(-orignialSize.x / 2 - 10, -orignialSize.y / 2 - 20 - 10);
            src_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
            src_mtx *= Affine.NewScaling(drawScale.Value);
            src_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);

            Affine img_mtx = Affine.NewIdentity();

            img_mtx *= Affine.NewTranslation(-orignialSize.x / 2 + 10, -orignialSize.y / 2 + 20 + 10);
            img_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
            img_mtx *= Affine.NewScaling(drawScale.Value);
            img_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);
            img_mtx.invert();

            MatterHackers.Agg.span_allocator sa = new span_allocator();

            span_interpolator_linear interpolator = new span_interpolator_linear(img_mtx);

            span_image_filter sg;

            switch (sourceImage.BitDepth)
            {
            case 24:
            {
                ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
                sg = new span_image_filter_rgb_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
            }
            break;

            case 32:
            {
                ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
                sg = new span_image_filter_rgba_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
            }
            break;

            default:
                throw new Exception("Bad sourc depth");
            }

            ScanlineRasterizer ras = new ScanlineRasterizer();

            ras.SetVectorClipBox(0, 0, Width, Height);
            ScanlineCachePacked8 sl = new ScanlineCachePacked8();
            //scanline_unpacked_8 sl = new scanline_unpacked_8();

            double r = orignialSize.x;

            if (orignialSize.y - 60 < r)
            {
                r = orignialSize.y - 60;
            }

            VertexSource.Ellipse ell = new VertexSource.Ellipse(orignialSize.x / 2.0 + 10,
                                                                orignialSize.y / 2.0 + 20 + 10,
                                                                r / 2.0 + 16.0,
                                                                r / 2.0 + 16.0, 200);

            VertexSourceApplyTransform tr = new VertexSourceApplyTransform(ell, src_mtx);

            ras.add_path(tr);
            //clippingProxy_pre.SetClippingBox(30, 0, (int)width(), (int)height());
            ScanlineRenderer scanlineRenderer = new ScanlineRenderer();

            scanlineRenderer.GenerateAndRender(ras, sl, clippingProxy_pre, sa, sg);

            if (false)             // this is test code to check different quality settings for scalling
            {
                Vector2 screenCenter = new Vector2(Width / 2, Height / 2);
                Vector2 deltaToMouse = mousePosition - screenCenter;
                double  angleToMouse = Math.Atan2(deltaToMouse.y, deltaToMouse.x);
                double  diagonalSize = Math.Sqrt(sourceImage.Width * sourceImage.Width + sourceImage.Height * sourceImage.Height);
                double  distToMouse  = deltaToMouse.Length;
                double  scalling     = distToMouse / diagonalSize;
                graphics2D.Render(sourceImage, Width / 2, Height / 2, angleToMouse - MathHelper.Tau / 8, scalling, scalling);
            }

            base.OnDraw(graphics2D);
        }
Exemple #6
0
		public override void OnDraw(Graphics2D graphics2D)
		{
			ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());

			if (orignialSize.x == 0)
			{
				orignialSize.x = WindowSize.x;
				orignialSize.y = WindowSize.y;
			}

			ImageBuffer destImageWithPreMultBlender = new ImageBuffer();
			switch (widgetsSubImage.BitDepth)
			{
				case 24:
					destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGR());
					break;

				case 32:
					destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGRA());
					break;

				default:
					throw new Exception("Unknown bit depth");
			}

			ImageClippingProxy clippingProxy_pre = new ImageClippingProxy(destImageWithPreMultBlender);

			clippingProxy_pre.clear(new RGBA_Floats(1.0, 1.0, 1.0));

			Affine src_mtx = Affine.NewIdentity();
			src_mtx *= Affine.NewTranslation(-orignialSize.x / 2 - 10, -orignialSize.y / 2 - 20 - 10);
			src_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
			src_mtx *= Affine.NewScaling(drawScale.Value);
			src_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);

			Affine img_mtx = Affine.NewIdentity();
			img_mtx *= Affine.NewTranslation(-orignialSize.x / 2 + 10, -orignialSize.y / 2 + 20 + 10);
			img_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
			img_mtx *= Affine.NewScaling(drawScale.Value);
			img_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);
			img_mtx.invert();

			MatterHackers.Agg.span_allocator sa = new span_allocator();

			span_interpolator_linear interpolator = new span_interpolator_linear(img_mtx);

			span_image_filter sg;
			switch (sourceImage.BitDepth)
			{
				case 24:
					{
						ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
						sg = new span_image_filter_rgb_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
					}
					break;

				case 32:
					{
						ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
						sg = new span_image_filter_rgba_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
					}
					break;

				default:
					throw new Exception("Bad sourc depth");
			}

			ScanlineRasterizer ras = new ScanlineRasterizer();
			ras.SetVectorClipBox(0, 0, Width, Height);
			ScanlineCachePacked8 sl = new ScanlineCachePacked8();
			//scanline_unpacked_8 sl = new scanline_unpacked_8();

			double r = orignialSize.x;
			if (orignialSize.y - 60 < r)
			{
				r = orignialSize.y - 60;
			}

			VertexSource.Ellipse ell = new VertexSource.Ellipse(orignialSize.x / 2.0 + 10,
				orignialSize.y / 2.0 + 20 + 10,
				r / 2.0 + 16.0,
				r / 2.0 + 16.0, 200);

			VertexSourceApplyTransform tr = new VertexSourceApplyTransform(ell, src_mtx);

			ras.add_path(tr);
			//clippingProxy_pre.SetClippingBox(30, 0, (int)width(), (int)height());
			ScanlineRenderer scanlineRenderer = new ScanlineRenderer();
			scanlineRenderer.GenerateAndRender(ras, sl, clippingProxy_pre, sa, sg);

			base.OnDraw(graphics2D);
		}
Exemple #7
0
        public override void OnDraw(Graphics2D graphics2D)
        {
            ImageBuffer        widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());
            ImageClippingProxy clippingProxy   = new ImageClippingProxy(widgetsSubImage);

            clippingProxy.clear(new ColorF(1, 1, 1));
            m_ras.SetVectorClipBox(0, 0, Width, Height);

            Affine move = Affine.NewTranslation(10, 10);

            Perspective shadow_persp = new Perspective(m_shape_bounds.Left, m_shape_bounds.Bottom,
                                                       m_shape_bounds.Right, m_shape_bounds.Top,
                                                       m_shadow_ctrl.polygon());

            IVertexSource shadow_trans;

            if (m_FlattenCurves.Checked)
            {
                shadow_trans = new VertexSourceApplyTransform(m_shape, shadow_persp);
            }
            else
            {
                shadow_trans = new VertexSourceApplyTransform(m_path, shadow_persp);
                // this will make it very smooth after the transform
                //shadow_trans = new conv_curve(shadow_trans);
            }

            // Render shadow
            m_ras.add_path(shadow_trans);
            ScanlineRenderer scanlineRenderer = new ScanlineRenderer();

            scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, new ColorF(0.2, 0.3, 0).ToColor());

            // Calculate the bounding box and extend it by the blur radius
            RectangleDouble bbox = new RectangleDouble();

            bounding_rect.bounding_rect_single(shadow_trans, 0, ref bbox);

            bbox.Left   -= m_radius.Value;
            bbox.Bottom -= m_radius.Value;
            bbox.Right  += m_radius.Value;
            bbox.Top    += m_radius.Value;

            if (m_method.SelectedIndex == 1)
            {
                // The recursive blur method represents the true Gaussian 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.Right += m_radius.Value;
                bbox.Top   += m_radius.Value;
            }

            stopwatch.Restart();

            if (m_method.SelectedIndex != 2)
            {
                // Create a new pixel renderer and attach it to the main one as a child image.
                // It returns true if the attachment succeeded. It fails if the rectangle
                // (bbox) is fully clipped.
                //------------------
#if SourceDepth24
                ImageBuffer image2 = new ImageBuffer(new BlenderBGR());
#else
                ImageBuffer image2 = new ImageBuffer(new BlenderBGRA());
#endif
                if (image2.Attach(widgetsSubImage, (int)bbox.Left, (int)bbox.Bottom, (int)bbox.Right, (int)bbox.Top))
                {
                    // Blur it
                    if (m_method.SelectedIndex == 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.
                        //------------------
                        stack_blur test = new stack_blur();
                        test.Blur(image2, agg_basics.uround(m_radius.Value), agg_basics.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(image2, m_radius.Value);
                    }
                }
            }
            else
            {
                /*
                 * // Blur separate channels
                 * //------------------
                 * if(m_channel_r.Checked)
                 * {
                 *      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.Checked)
                 * {
                 *      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.Checked)
                 * {
                 *      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 = stopwatch.ElapsedMilliseconds;

            // Render the shape itself
            //------------------
            if (m_FlattenCurves.Checked)
            {
                m_ras.add_path(m_shape);
            }
            else
            {
                m_ras.add_path(m_path);
            }

            scanlineRenderer.RenderSolid(clippingProxy, m_ras, m_sl, new ColorF(0.6, 0.9, 0.7, 0.8).ToColor());

            graphics2D.DrawString(string.Format("{0:F2} ms", tm), 140, 30);
            base.OnDraw(graphics2D);
        }