コード例 #1
0
ファイル: Test.cs プロジェクト: masums/Crow
        public void GraphicObject()
        {
            string [] tests = new string [] { "0", "1", "3", "4", "5" };

            foreach (string s in tests)
            {
                string fileName = Path.Combine("Interfaces", s + ".crow");
                iface.AddWidget(fileName);

                iface.Update();
                iface.Update();

                using (Cairo.Surface surf = new Cairo.ImageSurface(iface.bmp,
                                                                   Cairo.Format.Argb32, iface.ClientRectangle.Width, iface.ClientRectangle.Height, iface.ClientRectangle.Width * 4)) {
                    surf.WriteToPng(@"tmp.png");
                    surf.WriteToPng(fileName + ".png");
                }


                byte [] model  = File.ReadAllBytes("ExpectedOutputs/" + s + ".png");
                byte [] result = File.ReadAllBytes(@"tmp.png");

                //CollectionAssert.AreEqual (model, result);

                iface.ClearInterface();
            }
        }
コード例 #2
0
ファイル: PathUtil.cs プロジェクト: snowdream1985/ImGui-1
        public static void SaveToPng(List <LibTessDotNet.ContourVertex> path)
        {
            if (path == null || path.Count <= 1)
            {
                return;
            }
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, (int)Form.current.Size.Width, (int)Form.current.Size.Height))
                using (Cairo.Context g = new Cairo.Context(surface))
                {
                    g.MoveTo(path[0].Position.X, path[0].Position.Y);
                    for (int i = 1; i < path.Count; i++)
                    {
                        var x0 = path[i - 1].Position.X;
                        var y0 = path[i - 1].Position.Y;
                        var x1 = path[i].Position.X;
                        var y1 = path[i].Position.Y;

                        g.LineTo(x1, y1);

                        {
                            // draw index number
                            g.RelMoveTo(5, 5);
                            g.ShowText(i.ToString());
                            g.MoveTo(x1, y1);

                            // draw arrow
                            var dx = x1 - x0;
                            var dy = y1 - y0;

                            if (MathEx.AmostZero(dx) && MathEx.AmostZero(dy))
                            {
                                continue;
                            }

                            var n0 = new Vector(-dy, dx); n0.Normalize();
                            var n1 = new Vector(dy, -dx); n1.Normalize();

                            var B = new Point(x1, y1);
                            var d = new Vector(x0 - x1, y0 - y1); d.Normalize();

                            var arrowEnd0 = B + 5 * (d + n0);
                            var arrowEnd1 = B + 5 * (d + n1);
                            g.MoveTo(x1, y1);
                            g.LineTo(new Cairo.PointD(arrowEnd0.X, arrowEnd0.Y));
                            g.MoveTo(x1, y1);
                            g.LineTo(new Cairo.PointD(arrowEnd1.X, arrowEnd1.Y));
                            g.MoveTo(x1, y1);
                        }
                    }
                    g.Stroke();
                    surface.WriteToPng(@"D:\contour_test.png");
                }
        }
コード例 #3
0
ファイル: PathUtil.cs プロジェクト: snowdream1985/ImGui-1
        public static void SaveToPng(List <List <Point> > paths, string filePath)
        {
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, 2000, 2000))
                using (Cairo.Context g = new Cairo.Context(surface))
                {
                    foreach (var path in paths)
                    {
                        if (path == null || path.Count <= 1)
                        {
                            return;
                        }
                        g.MoveTo(path[0].X, path[0].Y);
                        for (int i = 1; i < path.Count; i++)
                        {
                            var x0 = path[i - 1].X;
                            var y0 = path[i - 1].Y;
                            var x1 = path[i].X;
                            var y1 = path[i].Y;

                            g.LineTo(x1, y1);

                            var dx = x1 - x0;
                            var dy = y1 - y0;

                            if (MathEx.AmostZero(dx) && MathEx.AmostZero(dy))
                            {
                                continue;
                            }

                            var n0 = new Vector(-dy, dx); n0.Normalize();
                            var n1 = new Vector(dy, -dx); n1.Normalize();

                            var B = new Point(x1, y1);
                            var d = new Vector(x0 - x1, y0 - y1); d.Normalize();

                            var arrowEnd0 = B + 5 * (d + n0);
                            var arrowEnd1 = B + 5 * (d + n1);
                            g.MoveTo(x1, y1);
                            g.LineTo(new Cairo.PointD(arrowEnd0.X, arrowEnd0.Y));
                            g.MoveTo(x1, y1);
                            g.LineTo(new Cairo.PointD(arrowEnd1.X, arrowEnd1.Y));
                            g.MoveTo(x1, y1);
                        }
                        g.Stroke();
                    }

                    surface.WriteToPng(filePath);
                }
        }
コード例 #4
0
ファイル: TestDrawing.cs プロジェクト: bvssvni/csharp-utils
        public void TestDrawLine()
        {
            var bytes = new byte[1024 * 4];
            var format = Cairo.Format.ARGB32;
            var image = new Cairo.ImageSurface (bytes, format, 32, 32, 32 * 4);
            var shape = new LineShape (0.0, 0.0, 32.0, 32.0);
            var look = new Look (SolidBrush.Red, SolidPen.Black);
            var op = new ShapeTree (look, shape);
            using (var context = new Cairo.Context (image)) {
                op.Draw (context);
            }

            image.WriteToPng ("testimages/line.png");
            image.Dispose ();
        }
コード例 #5
0
        public Gdk.Pixbuf Icon(int size)
        {
            Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, size, size);
            Gdk.Pixbuf         ret;

            Style         = DrawStyle.Icon;
            Cache.Enabled = false;

            using (Cairo.Context ct = new Cairo.Context(surface))
            {
                ct.Rectangle(0, 0, size, size);
                ct.Clip();

                ct.Translate(0, 0);
                ct.Scale(size, size);

                ct.LineWidth = 1.0 / size;

                Draw(ct);

                byte[] data = ConvertColorSpace(surface.Data);

                try
                {
                    ret = new Gdk.Pixbuf(data, Gdk.Colorspace.Rgb, true, 8, size, size, surface.Stride);
                }
                catch
                {
                    // Some stupid bug in older mono, fallback strategy
                    string filename = System.IO.Path.GetTempFileName();

                    if (System.IO.File.Exists(filename))
                    {
                        System.IO.File.Delete(filename);
                    }

                    surface.WriteToPng(filename);
                    ret = new Gdk.Pixbuf(filename);
                    System.IO.File.Delete(filename);
                }
            }

            Cache.Enabled = true;
            Style         = DrawStyle.Normal;

            return(ret);
        }
コード例 #6
0
ファイル: GameImage.cs プロジェクト: nated099/gbrainy
        // TODO: We need a parameter here because not all the views are games
        // we need to extend the concept of view to include Widgets
        public bool CreateImage(IDrawable drawable, string file)
        {
            Cairo.ImageSurface cairo_image      = null;
            gbrainy.Core.Main.CairoContextEx cr = null;

            try
            {
                file        = Path.GetFullPath(file);
                cairo_image = new Cairo.ImageSurface(Cairo.Format.ARGB32, IMAGE_WIDTH, IMAGE_HEIGHT);
                cr          = new gbrainy.Core.Main.CairoContextEx(cairo_image, "sans 12", 96);

                // Draw Image
                drawable.Draw(cr, IMAGE_WIDTH, IMAGE_WIDTH, false);
                cairo_image.WriteToPng(file);

                if (File.Exists(file) == false)
                {
                    Logger.Error("Game.CreateImage. Error writting {0}", file);
                }
                else
                {
                    Logger.Debug("Game.CreateImage. Wrote image {0}", file);
                }
            }

            catch (Exception e)
            {
                Logger.Error("Game.CreateImage. Error writting {0} {1}", file, e);
                return(false);
            }

            finally
            {
                if (cr != null)
                {
                    ((IDisposable)cr).Dispose();
                }

                if (cairo_image != null)
                {
                    ((IDisposable)cairo_image).Dispose();
                }
            }

            return(true);
        }
コード例 #7
0
ファイル: Util.cs プロジェクト: peter-819/ImGui
        internal static void DrawNode(Node node, [CallerMemberName] string memberName = "")
        {
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, (int)node.Rect.Width, (int)node.Rect.Height))
                using (Cairo.Context context = new Cairo.Context(surface))
                {
                    Draw(context, node);

                    if (!Directory.Exists(OutputPath))
                    {
                        Directory.CreateDirectory(OutputPath);
                    }

                    string filePath = OutputPath + "\\" + DateTime.UtcNow.ToString("yyyy-MM-dd_HH-mm-ss-fff_") + surface.GetHashCode() + memberName + ".png";
                    surface.WriteToPng(filePath);
                    Util.OpenImage(filePath);
                }
        }
コード例 #8
0
        public void ShouldGetCorrectOutline()
        {
            ITextContext textContext = new TypographyTextContext(
                "0123456", FontFile, 36,
                FontStretch.Normal, FontStyle.Normal, FontWeight.Normal,
                1000, 100,
                TextAlignment.Leading);

            // prepare debug contexts
            {
                surface = new Cairo.ImageSurface(Cairo.Format.Argb32, 2000, 2000);
                g       = new Cairo.Context(surface);
                g.SetSourceRGBA(1, 1, 1, 1);
                g.Paint();
                g.SetSourceRGBA(0, 0, 0, 1);
                g.LineWidth = 1;
            }

            // build path
            CairoPathBuilder cairoPathBuilder;
            {
                cairoPathBuilder = new CairoPathBuilder(g, 0, 0, 1);
                textContext.Build(Point.Zero, cairoPathBuilder);
            }

            // show debug results
            // image
            {
                surface.WriteToPng(PathImagePath);
                g.Dispose();

                Assert.False(PathImagePath.Contains(" "));
                // open the image in Windows Photo Viewer
                Process.Start(@"C:\WINDOWS\System32\rundll32.exe", @"""C:\Program Files\Windows Photo Viewer\PhotoViewer.dll"", ImageView_Fullscreen " + PathImagePath);
            }
            //text
            {
                var text = cairoPathBuilder.Result;
                File.WriteAllText(PathTextPath, text);
                Process.Start(@"notepad", PathTextPath);
            }

            // Now, check if the output text and image shows a right outline of the text.
        }
コード例 #9
0
ファイル: TestDrawing.cs プロジェクト: bvssvni/csharp-utils
        public void TestDrawEllipse()
        {
            var bytes = new byte[1024 * 4];
            var format = Cairo.Format.ARGB32;
            var image = new Cairo.ImageSurface (bytes, format, 32, 32, 32 * 4);
            var shape = new EllipseShape ();
            shape.Rectangle = new Rectangle () {
                X = 10.0,
                Y = 4.0,
                Width = 12.0,
                Height = 18.0
            };
            var look = new Look (SolidBrush.Red, SolidPen.Black);
            var op = new ShapeTree (look, shape);
            using (var context = new Cairo.Context (image)) {
                op.Draw (context);
            }

            image.WriteToPng ("testimages/ellipse.png");
            image.Dispose ();
        }
コード例 #10
0
ファイル: GlyphReaderFacts.cs プロジェクト: jangocheng/ImGui
            public void Read(string fontFileName, char character, int fontSize)
            {
                Typeface typeFace;

                using (var fs = Utility.ReadFile(Utility.FontDir + fontFileName))
                {
                    var reader = new OpenFontReader();
                    typeFace = reader.Read(fs);
                }

                Glyph glyph = typeFace.Lookup(character);

                // read polygons and bezier segments
                GlyphLoader.Read(glyph, out var polygons, out var bezierSegments);

                Rect aabb = new Rect(polygons[0][0], polygons[0][1]);

                //print to test output
                //calcualte the aabb
                for (int i = 0; i < polygons.Count; i++)
                {
                    o.WriteLine("Polygon " + i);
                    var polygon = polygons[i];
                    foreach (var p in polygon)
                    {
                        aabb.Union(p);
                        o.WriteLine("{0}, {1}", (int)p.X, (int)p.Y);
                    }
                    o.WriteLine("");
                }

                foreach (var segment in bezierSegments)
                {
                    aabb.Union(segment.Item1);
                    aabb.Union(segment.Item2);
                    aabb.Union(segment.Item3);
                    o.WriteLine("<{0}, {1}> <{2}, {3}> <{4}, {5}>",
                                (int)segment.Item1.X, (int)segment.Item1.Y,
                                (int)segment.Item2.X, (int)segment.Item2.Y,
                                (int)segment.Item3.X, (int)segment.Item3.Y);
                }

                o.WriteLine("");

                // draw to an image
                using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, 2000, 2000))
                    using (Cairo.Context g = new Cairo.Context(surface))
                    {
                        g.Translate(-aabb.Min.X, -aabb.Min.Y);

                        for (var i = 0; i < polygons.Count; i++)
                        {
                            var polygon = polygons[i];
                            g.MoveTo(polygon[0].X, polygon[0].Y);
                            foreach (var point in polygon)
                            {
                                g.LineTo(point.X, point.Y);
                            }
                            g.ClosePath();
                        }
                        g.SetSourceColor(new Cairo.Color(0, 0, 0));
                        g.LineWidth = 2;
                        g.StrokePreserve();
                        g.SetSourceColor(new Cairo.Color(0.8, 0, 0, 0.6));
                        g.Fill();

                        foreach (var segment in bezierSegments)
                        {
                            var p0 = segment.Item1;
                            var c  = segment.Item2;
                            var p1 = segment.Item3;
                            g.MoveTo(p0.X, p0.Y);
                            g.QuadraticTo(c.X, c.Y, p1.X, p1.Y);
                        }

                        g.LineWidth = 4;
                        g.SetSourceColor(CairoEx.ColorRgb(0, 122, 204));
                        g.Stroke();

                        var path =
                            $"{OutputPath}\\GlyphReaderFacts.TheReadMethod.Read_{fontFileName}_{character}_{fontSize}.png";
                        surface.WriteToPng(path);

                        Util.OpenImage(path);

                        // Now inspect the image to check whether the glyph is correct
                        // TODO Are there a better way to do such kind of unit-test?
                    }
            }
コード例 #11
0
        public void ShowGlyphAsDirectedContours_Cairo()
        {
            //load the glyph
            Typeface typeFace;

            using (var fs = Utility.ReadFile(Utility.FontDir + fontFileName))
            {
                var reader = new OpenFontReader();
                typeFace = reader.Read(fs);
            }
            Glyph  glyph       = typeFace.Lookup(character);
            Bounds boundingBox = typeFace.Bounds;
            short  ascender    = typeFace.Ascender;

            //read polygons and quadratic bezier segments
            GlyphLoader.Read(glyph, out var polygons, out var quadraticBezierSegments);

            //The actual position of points should apply ascender offset
            var offset = new Vector(0, ascender);

            // draw to an image
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32,
                                                                       boundingBox.XMax - boundingBox.XMin,
                                                                       boundingBox.YMax - boundingBox.YMin))
                using (Cairo.Context g = new Cairo.Context(surface))
                {
                    //set surface back ground to white (1,1,1,1)
                    g.SetSourceColor(CairoEx.ColorWhite);
                    g.Paint();

                    //polygons
                    for (var i = 0; i < polygons.Count; i++)
                    {
                        var polygon    = polygons[i];
                        var startPoint = polygon[0] + offset;
                        g.MoveTo(startPoint.X, startPoint.Y);
                        var previousPoint = startPoint;
                        foreach (var point in polygon)
                        {
                            var p = point + offset;
                            g.LineTo(p.X, p.Y);
                            g.DrawArrow(previousPoint, p);
                            previousPoint = p;
                        }
                        g.LineTo(startPoint.X, startPoint.Y);
                        g.DrawArrow(previousPoint, startPoint);
                    }
                    g.LineWidth = polygonLineWidth;
                    g.SetSourceColor(polygonColor.ToCairoColor());
                    g.Stroke();

                    //quadratic bezier segments
                    foreach (var segment in quadraticBezierSegments)
                    {
                        var p0 = segment.Item1 + offset;
                        var c  = segment.Item2 + offset;
                        var p1 = segment.Item3 + offset;
                        g.MoveTo(p0.X, p0.Y);
                        g.QuadraticTo(c.X, c.Y, p1.X, p1.Y);
                    }
                    g.LineWidth = quadraticLineWidth;
                    g.SetSourceColor(quadraticSegmentColor.ToCairoColor());
                    g.Stroke();

                    //start points
                    g.SetSourceColor(startPointColor.ToCairoColor());
                    for (var i = 0; i < polygons.Count; i++)
                    {
                        var polygon    = polygons[i];
                        var startPoint = polygon[0] + offset;
                        g.Arc(startPoint.x, startPoint.y, 10, 0, System.Math.PI * 2);
                        g.Fill();
                    }

                    //show the image of contours
                    var path = $"{OutputDir}{Path.DirectorySeparatorChar}{fontFileName}_{character}.png";
                    surface.WriteToPng(path);
                    Util.OpenImage(path);
                }
        }
コード例 #12
0
ファイル: GameImage.cs プロジェクト: GNOME/gbrainy
        // TODO: We need a parameter here because not all the views are games
        // we need to extend the concept of view to include Widgets
        public bool CreateImage(IDrawable drawable, string file)
        {
            Cairo.ImageSurface cairo_image = null;
            gbrainy.Core.Main.CairoContextEx cr = null;

            try
            {
                file = Path.GetFullPath (file);
                cairo_image = new Cairo.ImageSurface (Cairo.Format.ARGB32, IMAGE_WIDTH, IMAGE_HEIGHT);
                cr = new gbrainy.Core.Main.CairoContextEx (cairo_image, "sans 12", 96);

                // Draw Image
                drawable.Draw (cr, IMAGE_WIDTH, IMAGE_WIDTH, false);
                cairo_image.WriteToPng (file);

                if (File.Exists (file) == false)
                    Logger.Error ("Game.CreateImage. Error writting {0}", file);
                else
                    Logger.Debug ("Game.CreateImage. Wrote image {0}", file);
            }

            catch (Exception e)
            {
                Logger.Error ("Game.CreateImage. Error writting {0} {1}", file, e);
                return false;
            }

            finally
            {
                if (cr != null)
                    ((IDisposable) cr).Dispose ();

                if (cairo_image != null)
                    ((IDisposable) cairo_image).Dispose ();
            }

                return true;
        }
コード例 #13
0
ファイル: GlyphReaderFacts.cs プロジェクト: masums/ImGui-1
            public void Read(string fontFileName, char character, int fontSize)
            {
                Typeface typeFace;

                using (var fs = Utility.ReadFile(Utility.FontDir + fontFileName))
                {
                    var reader = new OpenFontReader();
                    typeFace = reader.Read(fs);
                }

                Glyph glyph = typeFace.Lookup(character);

                // read polygons and bezier segments
                var polygons       = new List <List <Point> >();
                var bezierSegments = new List <(Point, Point, Point)>();

                GlyphLoader.Read(glyph, out polygons, out bezierSegments);

                //print to test output
                for (int i = 0; i < polygons.Count; i++)
                {
                    o.WriteLine("Polygon " + i);
                    var polygon = polygons[i];
                    foreach (var p in polygon)
                    {
                        o.WriteLine("{0}, {1}", (int)p.X, (int)p.Y);
                    }
                    o.WriteLine("");
                }

                foreach (var segment in bezierSegments)
                {
                    o.WriteLine("<{0}, {1}> <{2}, {3}> <{4}, {5}>",
                                (int)segment.Item1.X, (int)segment.Item1.Y,
                                (int)segment.Item2.X, (int)segment.Item2.Y,
                                (int)segment.Item3.X, (int)segment.Item3.Y);
                }

                o.WriteLine("");

                //FIXME move/scale the rendered glyph to visible region of the cairo surface.

                // draw to an image
                using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, 2000, 2000))
                    using (Cairo.Context g = new Cairo.Context(surface))
                    {
                        for (int i = 0; i < polygons.Count; i++)
                        {
                            var polygon = polygons[i];
                            g.MoveTo(polygon[0].X, polygon[0].Y);
                            foreach (var point in polygon)
                            {
                                g.LineTo(point.X, point.Y);
                            }
                            g.ClosePath();
                        }
                        g.SetSourceColor(new Cairo.Color(0, 0, 0));
                        g.LineWidth = 2;
                        g.StrokePreserve();
                        g.SetSourceColor(new Cairo.Color(0.8, 0, 0));
                        g.Fill();

                        foreach (var segment in bezierSegments)
                        {
                            var p0 = segment.Item1;
                            var c  = segment.Item2;
                            var p1 = segment.Item3;
                            g.MoveTo(p0.X, p0.Y);
                            g.QuadraticTo(c.X, c.Y, p1.X, p1.Y);
                        }
                        g.SetSourceColor(new Cairo.Color(0.5, 0.5, 0));
                        g.Stroke();

                        var path = string.Format("D:\\ImGui.UnitTest\\GlyphReaderFacts.TheReadMethod.Read_{0}_{1}_{2}.png",
                                                 fontFileName, character, fontSize);
                        surface.WriteToPng(path);

                        Util.OpenImage(path);

                        // Now inspect the image to check whether the glyph is correct
                        // TODO Are there a better way to do such kind of unit-test?
                    }
            }
コード例 #14
0
ファイル: DvdMenu.cs プロジェクト: GNOME/mistelix
        public void Save(string file)
        {
            Cairo.ImageSurface s = new Cairo.ImageSurface (Cairo.Format.Rgb24, project.Details.Width, project.Details.Height);
            Cairo.Context cr = new Cairo.Context (s);
            bool previous = asynchronous;

            asynchronous = false;
            Draw (cr, null);
            asynchronous = previous;

            s.WriteToPng (file);
            ((IDisposable)cr).Dispose ();
            s.Destroy ();
        }
コード例 #15
0
ファイル: Spumux.cs プロジェクト: GNOME/mistelix
        string GenerateMenus()
        {
            StringBuilder sb = new StringBuilder (2048);
            Cairo.ImageSurface shigh = new Cairo.ImageSurface (Cairo.Format.ARGB32, project.Details.Width, project.Details.Height);
            Cairo.Context chight = new Cairo.Context (shigh);

            Cairo.ImageSurface snormal = new Cairo.ImageSurface (Cairo.Format.ARGB32, project.Details.Width, project.Details.Height);
            Cairo.Context cnormal = new Cairo.Context (snormal);

            for (int i = 0; i < project.Buttons.Count; i++)
            {
                Button button = (Button)project.Buttons [i];
                sb.Append ("   <button name = \"button" + i + "\"\n");
                sb.Append ("    x0 = \"" + project.Buttons[i].X + "\"\n");
                sb.Append ("    y0 = \"" + project.Buttons[i].Y + "\"\n");
                sb.Append ("    x1 = \"" + (project.Buttons[i].X + button.DrawingBoxWidth) + "\"\n");
                sb.Append ("    y1 = \"" + (project.Buttons[i].Y + button.DrawingBoxHeight) + "\"\n");

                sb.Append ("    down = \"ActionDown\"\n");
                sb.Append ("    up = \"ActionUp\"\n");
                sb.Append ("   />\n");
                DrawButtons (button, chight, cnormal);
            }

            // Quantize the images given
            {
                // See: http://www.cairographics.org/manual/bindings-surfaces.html
                byte [] pixels_normal = QuantizeSurface (snormal);
                Cairo.ImageSurface snormal_quantized =  new Cairo.ImageSurface (ref pixels_normal, snormal.Format, snormal.Width, snormal.Height, snormal.Stride);

                byte [] pixels_high = QuantizeSurface (shigh);
                Cairo.ImageSurface shigh_quantized =  new Cairo.ImageSurface (ref pixels_high, shigh.Format, shigh.Width, shigh.Height, shigh.Stride);

                snormal_quantized.WriteToPng (project.FileToFullPath (menu_normal));
                shigh_quantized.WriteToPng (project.FileToFullPath (menu_highlight));

                snormal_quantized.Destroy ();
                shigh_quantized.Destroy ();
            }

            if (Mistelix.Debugging)
            {
                snormal.WriteToPng (project.FileToFullPath ("menu_normal_unquantized.png"));
                shigh.WriteToPng (project.FileToFullPath ("menu_highlight_unquantized.png"));
            }

            ((IDisposable)cnormal).Dispose ();
            ((IDisposable)chight).Dispose ();
            shigh.Destroy ();
            snormal.Destroy ();
            return sb.ToString ();
        }