/// <summary> /// Function to read the kerning pairs for the font, if they exist. /// </summary> /// <param name="fontFile">Font file to read.</param> private static Dictionary <GorgonKerningPair, int> ReadKernPairs(GorgonChunkFileReader fontFile) { var result = new Dictionary <GorgonKerningPair, int>(); GorgonBinaryReader reader = fontFile.OpenChunk(KernDataChunk); // Read optional kerning information. int kernCount = reader.ReadInt32(); for (int i = 0; i < kernCount; ++i) { var kernPair = new GorgonKerningPair(reader.ReadChar(), reader.ReadChar()); result[kernPair] = reader.ReadInt32(); } fontFile.CloseChunk(); return(result); }
/// <summary> /// Function to read the meta data for font data within a stream. /// </summary> /// <param name="stream">The stream containing the metadata to read.</param> /// <returns> /// The font meta data as a <see cref="IGorgonFontInfo"/> value. /// </returns> protected override IGorgonFontInfo OnGetMetaData(Stream stream) { GorgonChunkFileReader fontFile = null; try { fontFile = new GorgonChunkFileReader(stream, new[] { FileHeader.ChunkID() }); fontFile.Open(); return(GetFontInfo(fontFile, null)); } finally { fontFile?.Close(); } }
/// <summary> /// Function to read the chunk containing the font information. /// </summary> /// <param name="fontFile">The chunk file reader containing the font data.</param> /// <param name="name">Used defined name for the font.</param> /// <returns>A new <seealso cref="IGorgonFontInfo"/> containing information about the font.</returns> private static GorgonFontInfo GetFontInfo(GorgonChunkFileReader fontFile, string name) { GorgonBinaryReader reader = fontFile.OpenChunk(FontInfoChunk); var info = new GorgonFontInfo(reader.ReadString(), reader.ReadSingle(), reader.ReadValue <FontHeightMode>(), name) { FontStyle = reader.ReadValue <FontStyle>(), DefaultCharacter = reader.ReadChar(), Characters = reader.ReadString(), AntiAliasingMode = reader.ReadValue <FontAntiAliasMode>(), OutlineColor1 = new GorgonColor(reader.ReadInt32()), OutlineColor2 = new GorgonColor(reader.ReadInt32()), OutlineSize = reader.ReadInt32(), PackingSpacing = reader.ReadInt32(), TextureWidth = reader.ReadInt32(), TextureHeight = reader.ReadInt32(), UsePremultipliedTextures = reader.ReadValue <bool>(), UseKerningPairs = reader.ReadBoolean() }; fontFile.CloseChunk(); return(info); }
/// <summary> /// Function to load the font data, with the specified size, from a stream. /// </summary> /// <param name="name">The name to assign to the font.</param> /// <param name="stream">The stream containing the font data.</param> /// <returns>A new <seealso cref="GorgonFont"/>, or, an existing font from the <seealso cref="GorgonFontFactory"/> cache.</returns> protected override GorgonFont OnLoadFromStream(string name, Stream stream) { var fontFile = new GorgonChunkFileReader(stream, new[] { FileHeader.ChunkID() }); GorgonFontInfo fontInfo = null; try { fontFile.Open(); fontInfo = GetFontInfo(fontFile, name); // If the font is already loaded, then just reuse it. if (Factory.HasFont(fontInfo)) { return(Factory.GetFont(fontInfo)); } GorgonBinaryReader reader = fontFile.OpenChunk(FontHeightChunk); // Read in information about the font height. float fontHeight = reader.ReadSingle(); float lineHeight = reader.ReadSingle(); float ascent = reader.ReadSingle(); float descent = reader.ReadSingle(); fontFile.CloseChunk(); if (fontFile.Chunks.Contains(BrushChunk)) { reader = fontFile.OpenChunk(BrushChunk); var brushType = (GlyphBrushType)reader.ReadInt32(); switch (brushType) { case GlyphBrushType.Hatched: fontInfo.Brush = new GorgonGlyphHatchBrush(); break; case GlyphBrushType.LinearGradient: fontInfo.Brush = new GorgonGlyphLinearGradientBrush(); break; case GlyphBrushType.PathGradient: fontInfo.Brush = new GorgonGlyphPathGradientBrush(); break; case GlyphBrushType.Texture: fontInfo.Brush = new GorgonGlyphTextureBrush(); break; default: fontInfo.Brush = new GorgonGlyphSolidBrush(); break; } fontInfo.Brush.ReadBrushData(reader); fontFile.CloseChunk(); } else { fontInfo.Brush = new GorgonGlyphSolidBrush(); } // If this font has kerning data, then load that in. IReadOnlyDictionary <GorgonKerningPair, int> kerningPairs = null; if (fontFile.Chunks.Contains(KernDataChunk)) { kerningPairs = ReadKernPairs(fontFile); } return(Factory.GetFont(fontInfo)); } finally { var brush = fontInfo?.Brush as IDisposable; brush?.Dispose(); fontFile.Close(); } }
public void ChunkReaderWriter() { const string stringChunk = "STRSCHNK"; const string intChunk = "INTSCHNK"; const string header = "TheHeader"; string[] strs = { "Cow", "Dog", "Cat", "Rabbit", "Duck" }; int[] ints = { 32, 11, 89, 64, 87, 77, 16, 2, 42 }; int expectedStrLength = strs.Length; int expectedIntsLength = ints.Length; using (MemoryStream stream = new MemoryStream()) { var fileWriter = new GorgonChunkFileWriter(stream, header.ChunkID()); fileWriter.Open(); GorgonBinaryWriter writer = fileWriter.OpenChunk(stringChunk.ChunkID()); writer.Write(strs.Length); foreach (string str in strs) { writer.Write(str); } fileWriter.CloseChunk(); writer = fileWriter.OpenChunk(intChunk.ChunkID()); writer.Write(ints.Length); foreach (int intVal in ints) { writer.Write(intVal); } fileWriter.CloseChunk(); fileWriter.Close(); stream.Position = 0; var fileReader = new GorgonChunkFileReader(stream, new[] { header.ChunkID() }); fileReader.Open(); GorgonBinaryReader reader = fileReader.OpenChunk(intChunk.ChunkID()); int numInts = reader.ReadInt32(); Assert.AreEqual(expectedIntsLength, numInts); int[] intVals = new int[numInts]; for (int i = 0; i < numInts; ++i) { intVals[i] = reader.ReadInt32(); } Assert.IsTrue(ints.SequenceEqual(intVals)); fileReader.CloseChunk(); reader = fileReader.OpenChunk(stringChunk.ChunkID()); int numStrs = reader.ReadInt32(); Assert.AreEqual(expectedStrLength, numStrs); string[] strVals = new string[numStrs]; for (int i = 0; i < numStrs; ++i) { strVals[i] = reader.ReadString(); } Assert.IsTrue(strs.SequenceEqual(strVals)); fileReader.CloseChunk(); fileReader.Close(); } }