diff --git a/ZenKit/Font.cs b/ZenKit/Font.cs index c9977de..9049888 100644 --- a/ZenKit/Font.cs +++ b/ZenKit/Font.cs @@ -1,48 +1,132 @@ using System; using System.Collections.Generic; +using System.IO; using System.Numerics; using System.Runtime.InteropServices; using ZenKit.Util; namespace ZenKit { + /// + /// A single font glyph. + /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct FontGlyph { + /// + /// The width of the glyph in pixels. + /// [MarshalAs(UnmanagedType.U1)] public byte width; + + /// + /// The position of the top left corner of the glyph in the font texture. + /// This value is not stored as absolute pixels but rather in percent of the width and + /// height of the image. Thus to calculate the real pixel position of the top left corner, + /// one multiplies `topLeft.x` by the width of the font texture and `topLeft.y` by its height. + /// + /// public Vector2 topLeft; + + /// + /// The position of the bottom right corner of the glyph in the font texture. + /// This value is not stored as absolute pixels but rather in percent of the width and + /// height of the image. Thus to calculate the real pixel position of the bottom right corner, + /// one multiplies `bottomRight.x` by the width of the font texture and `bottomRight.y` by its height. + /// + /// public Vector2 bottomRight; } + /// + /// Represents a ZenGin font file. + /// Fonts in the ZenGin consist of a font definition file and a font texture. This class represents the former. + /// Font + /// definition files contain a set of glyphs which define the extents of a + /// Windows-1252 encoded character within the font texture + /// file. Font files can be identified most easily by their .FNT extension or alternatively through the + /// "1\n" + /// string at the beginning of the file. + /// + /// public interface IFont : ICacheable { + /// + /// The name of this font. + /// public string Name { get; } + + /// + /// The height of each glyph of this font in pixels. + /// public int Height { get; } + + /// + /// All glyphs of this font. + /// ZenGin fonts contain characters present in the + /// Windows-1252 character encoding + /// which is generally used by Gothic and Gothic II. The returned list contains these glyphs in order. + /// Some glyphs may not actually be present in the font texture. For those glyphs, the stored UV-coordinates will be + /// invalid in some way (ie. they may point to a pixel not actually in the texture or be negative). + /// + /// + /// Repeated access to this property will lead to poor performance if access to a native ZenKit object is + /// required. Either cache the value in a variable or use . + /// + /// public List Glyphs { get; } + + /// + /// The total number of glyphs stored in this font. + /// public int GlyphCount { get; } + /// + /// Get a single glyph of this font. + /// + /// + /// The index of the glyph to get. Corresponds to a + /// Windows-1252 code point. + /// + /// The font glyph at the given + /// + /// + /// public FontGlyph GetGlyph(int index); } + /// + /// A ZenKit font object which has been fully loaded into C#. An object of this type is independent from any native + /// object and incurs none of its disadvantages. + /// [Serializable] public class CachedFont : IFont { + /// public string Name { get; set; } + + /// public int Height { get; set; } + + /// public List Glyphs { get; set; } + + /// public int GlyphCount => Glyphs.Count; + /// public IFont Cache() { return this; } + /// public bool IsCached() { return true; } + /// public FontGlyph GetGlyph(int index) { return Glyphs[index]; @@ -53,36 +137,77 @@ public class Font : IFont { private readonly UIntPtr _handle; + /// + /// Loads a ZenGin font from the given file on disk using ZenKit. + /// + /// + /// For example: + /// + /// var font = new Font("FONT_OLD_20.FNT"); + /// + /// + /// The path of the font file (usually ends in .FNT. + /// Thrown if loading the font fails for any reason. public Font(string path) { _handle = Native.ZkFont_loadPath(path); - if (_handle == UIntPtr.Zero) throw new Exception("Failed to load font"); + if (_handle == UIntPtr.Zero) throw new IOException("Failed to load font"); } + /// + /// Loads a ZenGin font from the given stream. + /// + /// + /// For example: + /// + /// var rd = new Read("FONT_OLD_20.FNT"); + /// var font = new Font(rd); + /// + /// + /// The stream to read from. + /// Thrown if loading the font fails for any reason. public Font(Read r) { _handle = Native.ZkFont_load(r.Handle); if (_handle == UIntPtr.Zero) throw new Exception("Failed to load font"); } + /// + /// Loads a ZenGin font from the given file on disk using ZenKit. + /// + /// + /// For example: + /// + /// var vfs = new Vfs(); + /// vfs.MountDisk("Textures.vdf", VfsOverwriteBehavior.Older); + /// var font = new Font(vfs, "FONT_OLD_20.FNT"); + /// + /// + /// + /// + /// Thrown if loading the font fails for any reason. public Font(Vfs vfs, string name) { _handle = Native.ZkFont_loadVfs(vfs.Handle, name); if (_handle == UIntPtr.Zero) throw new Exception("Failed to load font"); } + /// public string Name => Native.ZkFont_getName(_handle).MarshalAsString() ?? throw new Exception("Failed to load font name"); + /// public int Height => (int)Native.ZkFont_getHeight(_handle); + /// public int GlyphCount => (int)Native.ZkFont_getGlyphCount(_handle); + /// public List Glyphs { get { - var glyphs = new List(256); + var glyphs = new List(GlyphCount); Native.ZkFont_enumerateGlyphs(_handle, (_, glyph) => { @@ -94,6 +219,7 @@ public List Glyphs } } + /// public IFont Cache() { return new CachedFont @@ -104,11 +230,13 @@ public IFont Cache() }; } + /// public bool IsCached() { return false; } + /// public FontGlyph GetGlyph(int index) { return Native.ZkFont_getGlyph(_handle, (ulong)index);