public void LoadGlyph() { Font font = new FontCollection().Install(TestFonts.SimpleFontFileData()).CreateFont(12); // Get letter A Glyph g = font.GetGlyph(41); GlyphInstance instance = g.Instance; Assert.Equal(20, instance.ControlPoints.Length); Assert.Equal(20, instance.OnCurves.Length); }
public void LoadFontWoff() { IFontInstance font = FontInstance.LoadFont(TestFonts.SimpleFontFileWoffData()); Assert.Equal("SixLaborsSampleAB regular", font.Description.FontName); Assert.Equal("Regular", font.Description.FontSubFamilyName); GlyphInstance glyph = font.GetGlyph('a'); var r = new GlyphRenderer(); glyph.RenderTo(r, 12, System.Numerics.Vector2.Zero, new System.Numerics.Vector2(72), 0); // the test font only has characters .notdef, 'a' & 'b' defined Assert.Equal(6, r.ControlPoints.Distinct().Count()); }
public bool GetAdvances(out float[] advances) { advances = null; GlyphInstance firstInstance = FontInstance.GetGlyph(FirstChar); float adv = firstInstance.AdvanceWidth * Size * (DrawDpi / CalcDpi) / firstInstance.SizeOfEm; for (int i = FirstChar + 1; i <= LastChar; i++) { GlyphInstance inst = FontInstance.GetGlyph(i); float iAdv = inst.AdvanceWidth * Size * (DrawDpi / CalcDpi) / inst.SizeOfEm; if (advances == null) { if (iAdv != adv) { advances = new float[CharCount]; for (int c = 0; c < i - FirstChar; c++) { advances[c] = adv; } advances[i - FirstChar] = iAdv; } } else { advances[i - FirstChar] = iAdv; } } if (advances == null) { advances = new float[1] { adv }; return(false); } return(true); }
/// <summary> /// Creates the <see cref="IPathCollection"/> for all the characters, also getting their colors, /// glyph sizes and render offsets. /// </summary> private IPathCollection[] CreatePaths(out Color?[][] colors, out System.Drawing.Point[] sizes, out Vector2[] offsets) { float glyphRenderY = Size / CalcDpi * FontInstance.Ascender / FontInstance.EmSize; ColorGlyphRenderer glyphRenderer = new ColorGlyphRenderer(); IPathCollection[] paths = new IPathCollection[CharCount]; sizes = new System.Drawing.Point[paths.Length]; offsets = new Vector2[paths.Length]; colors = null; for (int i = 0; i < paths.Length; i++) { char c = (char)(i + FirstChar); glyphRenderer.Reset(); GlyphInstance glyphInstance = FontInstance.GetGlyph(c); glyphInstance.RenderTo(glyphRenderer, Size, new Vector2(0, glyphRenderY), new Vector2(DrawDpi, DrawDpi), 0); IPathCollection p = glyphRenderer.Paths; RectangleF bounds = p.Bounds; float area = bounds.Width * bounds.Height; if (float.IsFinite(area) && area != 0 && (c > char.MaxValue || !char.IsWhiteSpace(c))) { paths[i] = p; sizes[i] = new System.Drawing.Point((int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height)); renderOffsets[i] = new Vector2(bounds.X, bounds.Y); } if (glyphRenderer.HasAnyPathColors()) { if (colors == null) { colors = new Color?[CharCount][]; } colors[i] = glyphRenderer.PathColors; } } return(paths); }
public unsafe FontAtlas(FontFamily fontFamily, int fontSize, IEnumerable <int> characters) { Stopwatch watch = new Stopwatch(); watch.Start(); Size = fontSize; Font font = new Font(fontFamily, fontSize); float factor = (float)fontSize / font.EmSize; List <PackingRectangle> glyphRectangles = new List <PackingRectangle>(); foreach (int character in characters) { GlyphInstance glyph = font.GetGlyph(character).Instance; glyphRectangles.Add(new PackingRectangle(0, 0, (uint)((glyph.LeftSideBearing + glyph.AdvanceWidth) * factor), (uint)(glyph.Height * factor), character)); } PackingRectangle[] rectArray = glyphRectangles.ToArray(); RectanglePacker.Pack(rectArray, out PackingRectangle bounds); Image <A8> image = new Image <A8>((int)bounds.Width, (int)bounds.Height); Characters = new Dictionary <char, CharacterData>(); image.Mutate(x => { foreach (PackingRectangle glyphRectangle in rectArray) { GlyphInstance glyph = font.GetGlyph(glyphRectangle.Id).Instance; Characters.Add((char)glyphRectangle.Id, new CharacterData() { uvX1 = glyphRectangle.X / (float)image.Width, uvX2 = (glyphRectangle.X + glyphRectangle.Width) / (float)image.Width, uvY1 = glyphRectangle.Y / (float)image.Height, uvY2 = (glyphRectangle.Y + glyphRectangle.Height) / (float)image.Height, xAdvance = glyph.AdvanceWidth * factor, height = glyph.Height * factor }); x.DrawText(((char)glyphRectangle.Id).ToString(), font, Color.White, new PointF(glyphRectangle.X, glyphRectangle.Y)); } }); image.TryGetSinglePixelSpan(out Span <A8> pixels); TextureId = GL.GenTexture(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, TextureId); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); fixed(A8 *pixelPointer = pixels) { GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, image.Width, image.Height, 0, PixelFormat.Alpha, PixelType.UnsignedByte, new IntPtr(pixelPointer)); } GL.GenerateTextureMipmap(TextureId); watch.Stop(); Console.WriteLine($"Font atlas with size {image.Width}x{image.Height} was created in {watch.ElapsedMilliseconds}ms!"); }
public override void apply(Bridge.Html5.CanvasRenderingContext2D context, GlyphInstance glyph) { throw new System.NotImplementedException(); }
public float GetAdvance(int size, int codepoint) { GlyphInstance inst = FontInstance.GetGlyph(codepoint); return(inst.AdvanceWidth * size / FontInstance.EmSize); }
public void Issue21_LoopDetectedLoadingGlyphs() { Font font = new FontCollection().Install(TestFonts.CarterOneFileData()).CreateFont(12); GlyphInstance g = font.Instance.GetGlyph('\0'); }
public override void apply(Bridge.Html5.CanvasRenderingContext2D context, GlyphInstance glyph) { apply(context); }