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)); }
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];
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)); } }
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? } }
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); }
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); }
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); } }
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? } }