public override void Draw(Painter p)
        {
            if (p is GdiPlusPainter)
            {
                DrawWithWinGdi((GdiPlusPainter)p);
                return;
            }
            AggPainter       p2      = (AggPainter)p;
            AggRenderSurface aggRdsf = p2.RenderSurface;
            var widgetsSubImage      = aggRdsf.DestImage;
            var scline = aggRdsf.ScanlinePacked8;
            int width  = (int)widgetsSubImage.Width;
            int height = (int)widgetsSubImage.Height;

            //change value ***
            if (isMaskSliderValueChanged)
            {
                generate_alpha_mask(aggRdsf.ScanlineRasToDestBitmap, aggRdsf.ScanlinePacked8, aggRdsf.ScanlineRasterizer, width, height);
                this.isMaskSliderValueChanged = false;
            }
            var rasterizer = aggRdsf.ScanlineRasterizer;

            rasterizer.SetClipBox(0, 0, width, height);
            //alphaMaskImageBuffer.AttachBuffer(alphaByteArray, 0, width, height, width, 8, 1);

            PixelFarm.Agg.Imaging.AlphaMaskAdaptor imageAlphaMaskAdaptor = new PixelFarm.Agg.Imaging.AlphaMaskAdaptor(widgetsSubImage, alphaMask);
            ClipProxyImage alphaMaskClippingProxy = new ClipProxyImage(imageAlphaMaskAdaptor);
            ClipProxyImage clippingProxy          = new ClipProxyImage(widgetsSubImage);
            ////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);
            Affine transform = Affine.NewMatix(
                AffinePlan.Translate(-lionShape.Center.x, -lionShape.Center.y),
                AffinePlan.Scale(lionScale, lionScale),
                AffinePlan.Rotate(angle + Math.PI),
                AffinePlan.Skew(skewX / 1000.0, skewY / 1000.0),
                AffinePlan.Translate(width / 2, height / 2));

            clippingProxy.Clear(Drawing.Color.White);
            ScanlineRasToDestBitmapRenderer sclineRasToBmp = aggRdsf.ScanlineRasToDestBitmap;
            // draw a background to show how the mask is working better
            int rect_w = 30;

            VectorToolBox.GetFreeVxs(out var v1);
            for (int i = 0; i < 40; i++)
            {
                for (int j = 0; j < 40; j++)
                {
                    if ((i + j) % 2 != 0)
                    {
                        VertexSource.RoundedRect rect = new VertexSource.RoundedRect(i * rect_w, j * rect_w, (i + 1) * rect_w, (j + 1) * rect_w, 0);
                        rect.NormalizeRadius();
                        // Drawing as an outline
                        rasterizer.AddPath(rect.MakeVxs(v1));
                        v1.Clear();
                        sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, scline, ColorEx.Make(.9f, .9f, .9f));
                    }
                }
            }
            VectorToolBox.ReleaseVxs(ref v1);

            ////int x, y;
            //// Render the lion
            ////VertexSourceApplyTransform trans = new VertexSourceApplyTransform(lionShape.Path, transform);

            ////var vxlist = new System.Collections.Generic.List<VertexData>();
            ////trans.DoTransform(vxlist);

            //var tmpVxs1 = new VertexStore();
            //lionShape.ApplyTransform(transform);

            throw new NotImplementedException();

            //sclineRasToBmp.RenderSolidAllPaths(alphaMaskClippingProxy,
            //       rasterizer,
            //       scline,
            //       tmpVxs1,
            //       lionShape.Colors,
            //       lionShape.PathIndexList,
            //       lionShape.NumPaths);

            ///*
            //// Render random Bresenham lines and markers
            //agg::renderer_markers<amask_ren_type> m(r);
            //for(i = 0; i < 50; i++)
            //{
            //    m.line_color(agg::rgba8(randGenerator.Next() & 0x7F,
            //                            randGenerator.Next() & 0x7F,
            //                            randGenerator.Next() & 0x7F,
            //                            (randGenerator.Next() & 0x7F) + 0x7F));
            //    m.fill_color(agg::rgba8(randGenerator.Next() & 0x7F,
            //                            randGenerator.Next() & 0x7F,
            //                            randGenerator.Next() & 0x7F,
            //                            (randGenerator.Next() & 0x7F) + 0x7F));

            //    m.line(m.coord(randGenerator.Next() % width), m.coord(randGenerator.Next() % height),
            //           m.coord(randGenerator.Next() % width), m.coord(randGenerator.Next() % height));

            //    m.marker(randGenerator.Next() % width, randGenerator.Next() % height, randGenerator.Next() % 10 + 5,
            //             agg::marker_e(randGenerator.Next() % 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<amask_ren_type> renderer_type;
            //renderer_type ren(r, profile);

            //typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
            //rasterizer_type ras(ren);
            //ras.round_cap(true);

            //for(i = 0; i < 50; i++)
            //{
            //    ren.Color = agg::rgba8(randGenerator.Next() & 0x7F,
            //                         randGenerator.Next() & 0x7F,
            //                         randGenerator.Next() & 0x7F,
            //                         //255));
            //                         (randGenerator.Next() & 0x7F) + 0x7F);
            //    ras.move_to_d(randGenerator.Next() % width, randGenerator.Next() % height);
            //    ras.line_to_d(randGenerator.Next() % width, randGenerator.Next() % height);
            //    ras.render(false);
            //}


            //// Render random circles with gradient
            //typedef agg::gradient_linear_color<color_type> grad_color;
            //typedef agg::gradient_circle grad_func;
            //typedef agg::span_interpolator_linear<> interpolator_type;
            //typedef agg::span_gradient<color_type,
            //                          interpolator_type,
            //                          grad_func,
            //                          grad_color> span_grad_type;

            //agg::trans_affine grm;
            //grad_func grf;
            //grad_color grc(agg::rgba8(0,0,0), agg::rgba8(0,0,0));
            //agg::ellipse ell;
            //agg::span_allocator<color_type> sa;
            //interpolator_type inter(grm);
            //span_grad_type sg(inter, grf, grc, 0, 10);
            //agg::renderer_scanline_aa<amask_ren_type,
            //                          agg::span_allocator<color_type>,
            //                          span_grad_type> rg(r, sa, sg);
            //for(i = 0; i < 50; i++)
            //{
            //    x = randGenerator.Next() % width;
            //    y = randGenerator.Next() % height;
            //    double r = randGenerator.Next() % 10 + 5;
            //    grm.reset();
            //    grm *= agg::trans_affine_scaling(r / 10.0);
            //    grm *= agg::trans_affine_translation(x, y);
            //    grm.invert();
            //    grc.colors(agg::rgba8(255, 255, 255, 0),
            //               agg::rgba8(randGenerator.Next() & 0x7F,
            //                          randGenerator.Next() & 0x7F,
            //                          randGenerator.Next() & 0x7F,
            //                          255));
            //    sg.color_function(grc);
            //    ell.init(x, y, r, r, 32);
            //    g_rasterizer.add_path(ell);
            //    agg::render_scanlines(g_rasterizer, g_scanline, rg);
            //}
            // */
            ////m_num_cb.Render(g_rasterizer, g_scanline, clippingProxy);
        }
        void GenerateMaskWithWinGdiPlus(int w, int h)
        {
            //1. create 32 bits for mask image
            this.a_alphaBmp = new System.Drawing.Bitmap(w, h);
            //2. create graphics based on a_alphaBmp
            using (System.Drawing.Graphics gfxBmp = System.Drawing.Graphics.FromImage(a_alphaBmp))
            {
                gfxBmp.Clear(System.Drawing.Color.Black);
                //ClipProxyImage clippingProxy = new ClipProxyImage(image);
                //clippingProxy.Clear(ColorRGBA.Black);
                VertexSource.Ellipse ellipseForMask = new PixelFarm.Agg.VertexSource.Ellipse();
                System.Random        randGenerator  = new Random(1432);
                int num = (int)maskAlphaSliderValue;
                int lim = num - 1;
                for (int i = 0; i < lim; ++i)
                {
                    ellipseForMask.Reset(randGenerator.Next() % w,
                                         randGenerator.Next() % h,
                                         randGenerator.Next() % 100 + 20,
                                         randGenerator.Next() % 100 + 20,
                                         100);
                    // set the color to draw into the alpha channel.
                    // there is not very much reason to set the alpha as you will get the amount of
                    // transparency based on the color you draw.  (you might want some type of different edeg effect but it will be minor).
                    //rasterizer.AddPath(ellipseForMask.MakeVxs());
                    //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack,
                    //   ColorRGBA.Make((int)((float)i / (float)num * 255), 0, 0, 255));

                    VectorToolBox.GetFreeVxs(out var v1);
                    VxsHelper.FillVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(v1), ColorEx.Make((int)((float)i / (float)num * 255), 0, 0, 255));
                    VectorToolBox.ReleaseVxs(ref v1);
                }
                //the last one
                ellipseForMask.Reset(Width / 2, Height / 2, 110, 110, 100);
                //fill
                VectorToolBox.GetFreeVxs(out var v2);
                VxsHelper.FillVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(v2), ColorEx.Make(0, 0, 0, 255));
                v2.Clear();// reuse later
                //rasterizer.AddPath(ellipseForMask.MakeVertexSnap());
                //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack, new ColorRGBA(0, 0, 0, 255));
                ellipseForMask.Reset(ellipseForMask.originX, ellipseForMask.originY, ellipseForMask.radiusX - 10, ellipseForMask.radiusY - 10, 100);
                //rasterizer.AddPath(ellipseForMask.MakeVertexSnap());
                //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack, new ColorRGBA(255, 0, 0, 255));

                VxsHelper.FillVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(v2), ColorEx.Make(255, 0, 0, 255));

                VectorToolBox.ReleaseVxs(ref v2);

                //for (i = 0; i < num; i++)
                //{
                //    if (i == num - 1)
                //    {
                //        ellipseForMask.Reset(Width / 2, Height / 2, 110, 110, 100);
                //        //fill
                //        VxsHelper.DrawVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(), new ColorRGBA(0, 0, 0, 255));
                //        //rasterizer.AddPath(ellipseForMask.MakeVertexSnap());
                //        //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack, new ColorRGBA(0, 0, 0, 255));
                //        ellipseForMask.Reset(ellipseForMask.originX, ellipseForMask.originY, ellipseForMask.radiusX - 10, ellipseForMask.radiusY - 10, 100);
                //        //rasterizer.AddPath(ellipseForMask.MakeVertexSnap());
                //        //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack, new ColorRGBA(255, 0, 0, 255));
                //        VxsHelper.DrawVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(), new ColorRGBA(255, 0, 0, 255));
                //    }
                //    else
                //    {
                //        ellipseForMask.Reset(randGenerator.Next() % w,
                //                 randGenerator.Next() % h,
                //                 randGenerator.Next() % 100 + 20,
                //                 randGenerator.Next() % 100 + 20,
                //                 100);
                //        // set the color to draw into the alpha channel.
                //        // there is not very much reason to set the alpha as you will get the amount of
                //        // transparency based on the color you draw.  (you might want some type of different edeg effect but it will be minor).
                //        //rasterizer.AddPath(ellipseForMask.MakeVxs());
                //        //sclineRasToBmp.RenderWithColor(clippingProxy, rasterizer, sclnPack,
                //        //   ColorRGBA.Make((int)((float)i / (float)num * 255), 0, 0, 255));
                //        VxsHelper.DrawVxsSnap(gfxBmp, ellipseForMask.MakeVertexSnap(), ColorRGBA.Make((int)((float)i / (float)num * 255), 0, 0, 255));
                //    }
                //}
            }
        }
Exemple #3
0
        void DrawB(Painter p)
        {
            p.Clear(PixelFarm.Drawing.Color.White);
            //--------------------------
            p.StrokeColor = PixelFarm.Drawing.Color.Black;
            p.StrokeWidth = 2.0f;


            using (VxsTemp.Borrow(out var v1, out var v2))
                using (VectorToolBox.Borrow(v1, out PathWriter writer))
                {
                    writer.MoveTo(20, 10);
                    writer.LineTo(60, 10);
                    writer.LineTo(20, 200);
                    writer.CloseFigure();

                    //aggPainter.LineJoin = this.LineJoin;
                    //aggPainter.LineCap = this.LineCap;
                    //
                    //----------------------------------------------------
                    //create a dash line


                    _dashGenLineWalker.ClearMarks(); //clear previous markers
                    //***
                    //you can customize what happend with the line segment
                    _dashGenLineWalker.AddMark(10, (outputVxs, cmd, x, y) =>
                    {
                        //solid
                        switch (cmd)
                        {
                        case VertexCmd.MoveTo:
                            outputVxs.AddMoveTo(x, y);
                            break;

                        case VertexCmd.LineTo:
                            outputVxs.AddLineTo(x, y);
                            break;
                        }
                    });
                    _dashGenLineWalker.AddMark(10, (outputVxs, cmd, x, y) =>
                    {
                        //whitespace, do nothing
                    });

                    //then generate dash by walking along v1
                    _dashGenLineWalker.Walk(v1, v2);
                    //aggPainter.Draw(vxs);

                    //test drawline
                    int    n = v2.Count;
                    double px = 0, py = 0;

                    for (int i = 0; i < n; ++i)
                    {
                        double    x, y;
                        VertexCmd cmd = v2.GetVertex(i, out x, out y);
                        switch (cmd)
                        {
                        case VertexCmd.MoveTo:
                            px = x;
                            py = y;

                            break;

                        case VertexCmd.LineTo:
                            p.DrawLine(px, py, x, y);

                            break;
                        }
                        px = x;
                        py = y;
                    }
                }
            //aggPainter.Draw(newvxs);
        }
Exemple #4
0
        void DrawA(Painter p)
        {
            p.Clear(PixelFarm.Drawing.Color.White);
            //--------------------------
            p.StrokeColor = PixelFarm.Drawing.Color.Black;
            p.StrokeWidth = 2.0f;
            p.FillColor   = PixelFarm.Drawing.Color.Black;
            //

            using (VxsTemp.Borrow(out var vxs))
                using (VectorToolBox.Borrow(vxs, out PathWriter writer))
                {
                    writer.MoveTo(30, 10);
                    writer.LineTo(60, 10);
                    writer.MoveTo(10, 100);
                    writer.LineTo(10, 50);
                    p.Draw(vxs);
                }


            //writer.MoveTo(100, 100);
            //writer.LineTo(20, 200);
            //aggPainter.LineJoin = this.LineJoin;
            //aggPainter.LineCap = this.LineCap;
            //
            //----------------------------------------------------
            ////create a dash line
            //VertexStore dashOutputVxs = new VertexStore();
            //LineWalker dashGenLineWalker = new LineWalker();
            ////***
            ////you can customize what happend with the line segment
            //dashGenLineWalker.AddMark(10, LineWalkDashStyle.Solid);
            //dashGenLineWalker.AddMark(10, LineWalkDashStyle.Blank);
            ////dashGenLineWalker.AddMark(2, LineWalkDashStyle.Solid);
            ////dashGenLineWalker.AddMark(2, LineWalkDashStyle.Blank);
            //dashGenLineWalker.Walk(vxs, dashOutputVxs);
            ////----------------------------------------------------



            //aggPainter.Draw(dashOutputVxs);
            ////test drawline
            //int n = newvxs.Count;
            //double px = 0, py = 0;
            //for (int i = 0; i < n; ++i)
            //{
            //    double x, y;
            //    VertexCmd cmd = newvxs.GetVertex(i, out x, out y);
            //    switch (cmd)
            //    {
            //        case VertexCmd.MoveTo:
            //            px = x;
            //            py = y;

            //            break;
            //        case VertexCmd.LineTo:
            //            aggPainter.Line(px, py, x, y);

            //            break;
            //    }
            //    px = x;
            //    py = y;
            //}
        }
Exemple #5
0
        public override void Draw(Painter p)
        {
            //specific for agg

            if (p is PixelFarm.CpuBlit.AggPainter)
            {
                var p2 = (PixelFarm.CpuBlit.AggPainter)p;
                AggRenderSurface   aggsx      = p2.RenderSurface;
                ScanlineRasterizer rasterizer = aggsx.ScanlineRasterizer;


                var widgetsSubImage = PixelProcessing.BitmapBlenderExtension.CreateSubBitmapBlender(aggsx.DestBitmapBlender, aggsx.GetClippingRect());
                aggsx.UseSubPixelLcdEffect = false;
                PixelProcessing.PixelBlenderBGRA normalBlender = new PixelProcessing.PixelBlenderBGRA();
                PixelProcessing.PixelBlenderBGRA gammaBlender  = new PixelProcessing.PixelBlenderBGRA(); //TODO: revisit, and fix this again
                gammaBlender.GammaValue  = this.GammaValue;
                gammaBlender.EnableGamma = true;
                var            rasterGamma         = new PixelProcessing.SubBitmapBlender(widgetsSubImage, gammaBlender);
                ClipProxyImage clippingProxyNormal = new ClipProxyImage(widgetsSubImage);
                ClipProxyImage clippingProxyGamma  = new ClipProxyImage(rasterGamma);
                clippingProxyNormal.Clear(Color.White);

                ScanlineUnpacked8 sl = new ScanlineUnpacked8();
                int size_mul         = (int)this.PixelSize;
                CustomScanlineRasToBmp_EnlargedSubPixelRendering ren_en = new CustomScanlineRasToBmp_EnlargedSubPixelRendering(size_mul, aggsx.DestBitmap);
                rasterizer.Reset();
                rasterizer.MoveTo(_x[0] / size_mul, _y[0] / size_mul);
                rasterizer.LineTo(_x[1] / size_mul, _y[1] / size_mul);
                rasterizer.LineTo(_x[2] / size_mul, _y[2] / size_mul);
                ren_en.RenderWithColor(clippingProxyGamma, rasterizer, sl, Color.Black);
                //----------------------------------------
                DestBitmapRasterizer sclineRasToBmp = aggsx.BitmapRasterizer;
                aggsx.UseSubPixelLcdEffect = false;
                sclineRasToBmp.RenderWithColor(clippingProxyGamma, rasterizer, sl, Color.Black);
                rasterizer.ResetGamma(new GammaNone());
                aggsx.UseSubPixelLcdEffect = false;
                //----------------------------------------

                using (VxsTemp.Borrow(out var v1, out var v2))
                    using (VectorToolBox.Borrow(v1, out PathWriter ps))
                    {
                        ps.Clear();
                        ps.MoveTo(_x[0], _y[0]);
                        ps.LineTo(_x[1], _y[1]);
                        ps.LineTo(_x[2], _y[2]);
                        ps.LineTo(_x[0], _y[0]);

                        rasterizer.AddPath(_stroke.MakeVxs(v1, v2));
                    }


                //----------------------------------------
                //Stroke stroke = new Stroke(ps);
                //stroke.Width = 2;
                //rasterizer.AddPath(stroke.MakeVxs(ps.MakeVxs()));

                //----------------------------------------

                sclineRasToBmp.RenderWithColor(clippingProxyNormal, rasterizer, sl, new Color(200, 0, 150, 160));
            }
        }
 void ReleaseVxs(ref VertexStore v)
 {
     VectorToolBox.ReleaseVxs(ref v);
 }
Exemple #7
0
        public override void Draw(Painter p)
        {
            if (UseBitmapExt)
            {
                p.RenderQuality = RenderQuality.Fast;
            }
            else
            {
                p.RenderQuality = RenderQuality.HighQuality;
            }

            int width  = 800;
            int height = 600;

            //clear the image to white
            // draw a circle
            p.Clear(Drawing.Color.White);

            //Ellipse ellipseVxsGen = new Ellipse(0, 0, 100, 50);
            using (VectorToolBox.Borrow(out Ellipse ellipseVxsGen))
                using (VectorToolBox.Borrow(out Stroke stroke))
                {
                    ellipseVxsGen.Set(0, 0, 100, 50);
                    stroke.Width = 3;

                    for (double angleDegrees = 0; angleDegrees < 180; angleDegrees += 22.5)
                    {
                        var mat = Affine.NewMatix(
                            AffinePlan.Rotate(MathHelper.DegreesToRadians(angleDegrees)),
                            AffinePlan.Translate(width / 2, 150));

                        using (VxsTemp.Borrow(out var v1, out var v2, out var v3))
                        {
                            ellipseVxsGen.MakeVxs(mat, v2);
                            p.FillColor = Drawing.Color.Yellow;
                            p.Fill(v2);
                            //------------------------------------
                            p.FillColor = Drawing.Color.Blue;
                            p.Fill(stroke.MakeVxs(v2, v3));
                        }
                    }
                }


            // and a little polygon
            using (VxsTemp.Borrow(out var v1))
                using (VectorToolBox.Borrow(v1, out PathWriter littlePoly))
                {
                    littlePoly.MoveTo(50, 50);
                    littlePoly.LineTo(150, 50);
                    littlePoly.LineTo(200, 200);
                    littlePoly.LineTo(50, 150);
                    littlePoly.LineTo(50, 50);
                    p.FillColor = Drawing.Color.Blue;
                    p.Fill(v1);
                }
            //---



            //----
            //test draw img



            //
            //g.Render(littlePoly.MakeVertexSnap(), ColorRGBA.Cyan);
            // draw some text
            // draw some text

            //var textPrinter = new TextPrinter();
            //textPrinter.CurrentActualFont = svgFontStore.LoadFont(SvgFontStore.DEFAULT_SVG_FONTNAME, 30);
            //new TypeFacePrinter("Printing from a printer", 30, justification: Justification.Center);

            //VertexStore vxs = textPrinter.CreateVxs("Printing from a printer".ToCharArray());
            //var affTx = Affine.NewTranslation(width / 2, height / 4 * 3);
            //VertexStore s1 = affTx.TransformToVxs(vxs);
            //p.FillColor = Drawing.Color.Black;
            //p.Fill(s1);
            ////g.Render(s1, ColorRGBA.Black);
            //p.FillColor = Drawing.Color.Red;
            //p.Fill(StrokeHelp.MakeVxs(s1, 1));
            ////g.Render(StrokeHelp.MakeVxs(s1, 1), ColorRGBA.Red);
            //var aff2 = Affine.NewMatix(
            //    AffinePlan.Rotate(MathHelper.DegreesToRadians(90)),
            //    AffinePlan.Translate(40, height / 2));
            //p.FillColor = Drawing.Color.Black;
            //p.Fill(aff2.TransformToVertexSnap(vxs));
            ////g.Render(aff2.TransformToVertexSnap(vxs), ColorRGBA.Black);
        }
        public override void Draw(PixelFarm.Drawing.Painter p)
        {
            p.Clear(Drawing.Color.White);
            p.StrokeColor = Color.Black;
            p.StrokeWidth = 2;
            p.StrokeColor = Color.Green;

            p.Draw(_triangleVxs);


            if (!ShowReconstructionCurve)
            {
                return;
            }

            //draw Ci line
            p.StrokeColor = Color.OrangeRed;
            DrawLine(p, a01, a12);
            DrawLine(p, a12, a20);
            DrawLine(p, a20, a01);
            //find B

            //DrawPoint(p, a01);
            //DrawPoint(p, a12);
            //DrawPoint(p, a20);

            BezierControllerArmPair c1 = BezierControllerArmPair.ReconstructControllerArms(v0, v1, v2);
            BezierControllerArmPair c2 = BezierControllerArmPair.ReconstructControllerArms(v1, v2, v0);
            BezierControllerArmPair c0 = BezierControllerArmPair.ReconstructControllerArms(v2, v0, v1);



            c0.UniformSmoothCoefficient = SmoothCoefficientValue;
            c1.UniformSmoothCoefficient = SmoothCoefficientValue;
            c2.UniformSmoothCoefficient = SmoothCoefficientValue;

            //DrawPoint(p, c0 = FindB(v0, v1, v2, out c1));
            //DrawPoint(p, b2 = FindB(v1, v2, v0, out c2));
            //DrawPoint(p, b0 = FindB(v2, v0, v1, out c0));

            p.StrokeColor = Color.Red;
            DrawControllerPair(p, c0);
            DrawControllerPair(p, c1);
            DrawControllerPair(p, c2);


            p.StrokeColor = Color.Blue;
            using (VxsTemp.Borrow(out var tmpVxs1, out var tmpVxs2))
                using (VectorToolBox.Borrow(tmpVxs1, out PathWriter pw))
                {
                    pw.MoveTo(c0.mid.X, c0.mid.y);

                    pw.Curve4(c0.right.x, c0.right.y, c1.left.x, c1.left.y, c1.mid.x, c1.mid.y); //1st curve

                    pw.Curve4(c1.right.x, c1.right.y, c2.left.x, c2.left.y, c2.mid.x, c2.mid.y); //2nd curve

                    pw.Curve4(c2.right.x, c2.right.y, c0.left.x, c0.left.y, c0.mid.x, c0.mid.y); //3rd curve

                    _curveflattener.MakeVxs(tmpVxs1, tmpVxs2);
                    p.Draw(tmpVxs2);
                }
        }
        public override void Draw(Painter p)
        {
            Painter painter = p;

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


            //-----------------------------------
            painter.Clear(Drawing.Color.White);
            //IImageReaderWriter backBuffer = ImageHelper.CreateChildImage(gx.DestImage, gx.GetClippingRect());
            //ChildImage image;
            //if (backBuffer.BitDepth == 32)
            //{
            //    image = new ChildImage(backBuffer, new PixelBlenderBGRA());
            //}
            //else
            //{
            //    if (backBuffer.BitDepth != 24)
            //    {
            //        throw new System.NotSupportedException();
            //    }
            //    image = new ChildImage(backBuffer, new PixelBlenderBGR());
            //}
            //ClipProxyImage dest = new ClipProxyImage(image);
            //gx.Clear(ColorRGBA.White);
            //gx.SetClippingRect(new RectInt(0, 0, Width, Height));
            //ScanlineRasToDestBitmapRenderer sclineRasToBmp = gx.ScanlineRasToDestBitmap;

            if (this.PerspectiveTransformType == Sample_Perspective.PerspectiveTransformType.Bilinear)
            {
                var      bound      = lionShape.Bounds;
                Bilinear txBilinear = Bilinear.RectToQuad(bound.Left,
                                                          bound.Bottom,
                                                          bound.Right,
                                                          bound.Top,
                                                          quadPolygonControl.GetInnerCoords());
                if (txBilinear.IsValid)
                {
                    VectorToolBox.GetFreeVxs(out var v3);
                    lionShape.ApplyTransform(txBilinear);
                    lionShape.Paint(painter);
                    RectD   lionBound = lionShape.Bounds;
                    Ellipse ell       = new Ellipse((lionBound.Left + lionBound.Right) * 0.5,
                                                    (lionBound.Bottom + lionBound.Top) * 0.5,
                                                    (lionBound.Right - lionBound.Left) * 0.5,
                                                    (lionBound.Top - lionBound.Bottom) * 0.5,
                                                    200);
                    VectorToolBox.ReleaseVxs(ref v3);

                    //



                    VectorToolBox.GetFreeVxs(out var v1, out var trans_ell);

                    txBilinear.TransformToVxs(ell.MakeVxs(v1), trans_ell);
                    painter.FillColor = ColorEx.Make(0.5f, 0.3f, 0.0f, 0.3f);
                    painter.Fill(trans_ell);
                    //-------------------------------------------------------------
                    //outline
                    double prevStrokeWidth = painter.StrokeWidth;
                    painter.StrokeWidth = 3;
                    painter.StrokeColor = ColorEx.Make(0.0f, 0.3f, 0.2f, 1.0f);
                    painter.Draw(trans_ell);
                    painter.StrokeWidth = prevStrokeWidth;


                    VectorToolBox.ReleaseVxs(ref v1, ref trans_ell);
                }
            }
            else
            {
                RectD r = lionShape.Bounds;

                var txPerspective = new Perspective(
                    r.Left, r.Bottom, r.Right, r.Top,
                    quadPolygonControl.GetInnerCoords());
                if (txPerspective.IsValid)
                {
                    lionShape.Paint(p, txPerspective); //transform -> paint

                    //painter.PaintSeries(txPerspective.TransformToVxs(lionShape.Vxs, v1),
                    //  lionShape.Colors,
                    //  lionShape.PathIndexList,
                    //  lionShape.NumPaths);
                    //--------------------------------------------------------------------------------------
                    //filled Ellipse
                    //1. create original fill ellipse
                    RectD lionBound     = lionShape.Bounds;
                    var   filledEllipse = new Ellipse((lionBound.Left + lionBound.Right) * 0.5,
                                                      (lionBound.Bottom + lionBound.Top) * 0.5,
                                                      (lionBound.Right - lionBound.Left) * 0.5,
                                                      (lionBound.Top - lionBound.Bottom) * 0.5,
                                                      200);

                    VectorToolBox.GetFreeVxs(out var v2, out var transformedEll);

                    txPerspective.TransformToVxs(filledEllipse.MakeVxs(v2), transformedEll);
                    painter.FillColor = ColorEx.Make(0.5f, 0.3f, 0.0f, 0.3f);
                    painter.Fill(transformedEll);
                    //--------------------------------------------------------
                    var prevStrokeW = painter.StrokeWidth;
                    painter.StrokeWidth = 3;
                    painter.StrokeColor = ColorEx.Make(0.0f, 0.3f, 0.2f, 1.0f);
                    painter.Draw(transformedEll);
                    painter.StrokeWidth = prevStrokeW;


                    VectorToolBox.ReleaseVxs(ref v2, ref transformedEll);
                }
            }

            //--------------------------
            // Render the "quad" tool and controls
            painter.FillColor = ColorEx.Make(0f, 0.3f, 0.5f, 0.6f);

            VectorToolBox.GetFreeVxs(out var v4);
            painter.Fill(quadPolygonControl.MakeVxs(v4));
            VectorToolBox.ReleaseVxs(ref v4);
        }