Пример #1
0
        public static GlyphTable Load(BinaryReader reader, uint[] locations)
        {
            var empty      = new Glyphs.EmptyGlyphLoader();
            var entryCount = locations.Length;
            var glyphCount = entryCount - 1; // last entry is a placeholder to the end of the table

            Glyphs.GlyphLoader[] glyphs = new Glyphs.GlyphLoader[glyphCount];
            for (var i = 0; i < glyphCount; i++)
            {
                if (locations[i] == locations[i + 1])
                {
                    // this is an empty glyphs;
                    glyphs[i] = empty;
                }
                else
                {
                    // move to start of glyph
                    reader.Seek(locations[i], System.IO.SeekOrigin.Begin);

                    glyphs[i] = GlyphLoader.Load(reader);
                }
            }

            return(new GlyphTable(glyphs));
        }
Пример #2
0
        public void ShowGlyphAsTextMesh_Builtin()
        {
            //load the glyph
            Typeface typeFace;

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

            Bounds boundingBox = typeFace.Bounds;
            short  ascender    = typeFace.Ascender;
            Glyph  glyph       = typeFace.Lookup(character);

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

            //construct text mesh
            TextMesh textMesh         = new TextMesh();
            Color    polygonFillColor = Color.Argb(128, 10, 10, 10);

            textMesh.AddTriangles(polygons, polygonFillColor,
                                  new Vector(0, ascender), Vector.Zero, 1, false);
            textMesh.AddBezierSegments(quadraticBezierSegments, polygonFillColor,
                                       new Vector(0, ascender), Vector.Zero, 1, false);
            var command = textMesh.Commands[^ 1];
Пример #3
0
            public void Read(string fontFileName, char character, string expectedImageFilePath)
            {
                Typeface typeFace;

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

                Typography.OpenFont.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, MathEx.RoundToInt(aabb.Width), MathEx.RoundToInt(aabb.Height)))
                    using (Cairo.Context g = new Cairo.Context(surface))
                    {
                        g.Translate(-aabb.Min.X, -aabb.Min.Y);
                        //essential: set surface back ground to white (1,1,1,1)
                        g.SetSourceColor(CairoEx.ColorWhite);
                        g.Paint();

                        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 = 4;
                        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();

                        //used to generate expected image
                        //surface.WriteToPng($"{Util.OutputPath}\\GlyphReaderFacts.TheReadMethod.Read_{fontFileName}_{character}.png");

                        var image         = Image.LoadPixelData <Bgra32>(Configuration.Default, surface.Data, surface.Width, surface.Height);
                        var expectedImage = Image.Load(expectedImageFilePath);
                        Assert.True(Util.CompareImage(expectedImage, image));
                    }
            }
Пример #4
0
            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?
                    }
            }
Пример #5
0
        public void ShowGlyphAsDirectedContours_Builtin()
        {
            //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);

            //polygons
            Geometry polygonGeometry;
            {
                var d = new PathGeometryBuilder();
                d.BeginPath();
                foreach (var polygon in polygons)
                {
                    var startPoint = polygon[0] + offset;
                    d.MoveTo(startPoint);
                    var previousPoint = startPoint;
                    foreach (var point in polygon.Skip(1))
                    {
                        var p = point + offset;
                        d.LineTo(p);
                        //DrawArrow(d, lastPoint, point);
                        previousPoint = p;
                    }
                    d.LineTo(startPoint);
                    //DrawArrow(d, lastPoint, point);
                    d.Stroke();
                }
                polygonGeometry = d.ToGeometry();
            }
            var polygonPen = new Pen(polygonColor, polygonLineWidth);

            //quadratic bezier segments
            Geometry quadraticGeometry;
            {
                var d = new PathGeometryBuilder();
                d.BeginPath();
                foreach (var qs in quadraticBezierSegments)
                {
                    d.MoveTo(qs.Item1 + offset);
                    d.QuadraticCurveTo(qs.Item2 + offset, qs.Item3 + offset);
                    d.Stroke();
                }
                quadraticGeometry = d.ToGeometry();
            }
            var quadraticPen = new Pen(quadraticSegmentColor, quadraticLineWidth);

            //start points
            Geometry startPointGeometry;
            {
                var d = new PathGeometryBuilder();
                for (var i = 0; i < polygons.Count; i++)
                {
                    var polygon    = polygons[i];
                    var startPoint = polygon[0] + offset;
                    d.Circle(startPoint, 10);
                    d.Fill();
                }
                startPointGeometry = d.ToGeometry();
            }
            var startPointBrush = new Brush(startPointColor);

            //create a DrawingVisual to hold geometries
            DrawingVisual drawingVisual = new DrawingVisual(0);

            //create geometries and save to DrawingVisual's content
            DrawingContext drawingContext = drawingVisual.RenderOpen();

            drawingContext.DrawGeometry(null, polygonPen, polygonGeometry);
            drawingContext.DrawGeometry(null, quadraticPen, quadraticGeometry);
            drawingContext.DrawGeometry(startPointBrush, null, startPointGeometry);
            drawingContext.Close();

            //draw the drawingVisual to image
            int width = boundingBox.XMax - boundingBox.XMin, height = boundingBox.YMax - boundingBox.YMin;

            Util.DrawDrawingVisualToImage(out var imageBytes, width, height, drawingVisual);

            //save and show the image
            var path = $"{OutputDir}{Path.DirectorySeparatorChar}{nameof(ShowGlyphAsDirectedContours_Builtin)}_{fontFileName}_{character}.png";

            Util.ShowRawPixelsFrom_glReadPixels_NotOpenFolder(imageBytes, width, height, path);
        }
Пример #6
0
        public void ShowGlyphAsOverlappingPolygon_Builtin()
        {
            //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);

            //polygons
            var      polygonBrush = new Brush(Color.Argb(128, 10, 10, 10));
            Geometry polygonGeometry;
            {
                var d = new PathGeometryBuilder();
                foreach (var polygon in polygons)
                {
                    if (polygon.Count == 0)
                    {
                        continue;
                    }

                    d.MoveTo(polygon[0] + offset);
                    foreach (var point in polygon.Skip(1))
                    {
                        d.LineTo(point + offset);
                    }
                    d.Fill();
                }
                polygonGeometry = d.ToGeometry();
            }

            //polygon points
            Geometry pointsGeometry;
            {
                var d = new PathGeometryBuilder();
                foreach (var polygon in polygons)
                {
                    foreach (var point in polygon)
                    {
                        d.Circle(point + offset, 5);
                        d.Fill();
                    }
                }
                pointsGeometry = d.ToGeometry();
            }
            var pointsBrush = new Brush(Color.Argb(200, 0, 0, 0));

            //create a DrawingVisual to hold geometries
            DrawingVisual drawingVisual = new DrawingVisual(0);

            //create geometries and save to DrawingVisual's content
            DrawingContext drawingContext = drawingVisual.RenderOpen();

            drawingContext.DrawGeometry(pointsBrush, null, pointsGeometry);
            drawingContext.DrawGeometry(polygonBrush, null, polygonGeometry);
            drawingContext.Close();

            //draw the drawingVisual to image
            int width = boundingBox.XMax - boundingBox.XMin, height = boundingBox.YMax - boundingBox.YMin;

            Util.DrawDrawingVisualToImage(out var imageBytes, width, height, drawingVisual);

            //save and show the image
            var path = $"{OutputDir}{Path.DirectorySeparatorChar}{nameof(ShowGlyphAsOverlappingPolygon_Builtin)}_{fontFileName}_{character}.png";

            Util.ShowRawPixelsFrom_glReadPixels_NotOpenFolder(imageBytes, width, height, path);
        }
Пример #7
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);
                }
        }
Пример #8
0
            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?
                    }
            }