/// <summary> /// Function to persist the shader data to a stream as a <see cref="GorgonChunkFile{T}"/>. /// </summary> /// <param name="stream">The stream to write the data into.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown when the stream is read only.</exception> /// <remarks> /// <para> /// This will write the shader data as <see cref="GorgonChunkFile{T}"/> formatted data into the supplied <paramref name="stream"/>. Shaders may take some time to compile, saving them to a binary /// format in a stream will help cut down on the time it takes to initialize an application. /// </para> /// <para> /// This makes use of the Gorgon <see cref="GorgonChunkFile{T}"/> format to allow flexible storage of data. The Gorgon shader format is broken into 2 chunks, both of which are available in the /// <see cref="GorgonShaderFactory.BinaryShaderMetaData"/>, and <see cref="GorgonShaderFactory.BinaryShaderByteCode"/> constants. The file header for the format is stored in the /// <see cref="GorgonShaderFactory.BinaryShaderFileHeader"/> constant. /// </para> /// <para> /// The file format is as follows: /// <list type="bullet"> /// <item> /// <term><see cref="GorgonShaderFactory.BinaryShaderFileHeader"/></term> /// <description>This describes the type of file, and the version.</description> /// </item> /// <item> /// <term><see cref="GorgonShaderFactory.BinaryShaderMetaData"/></term> /// <description>Shader metadata, such as the <see cref="Core.ShaderType"/> (<see cref="int"/>), debug flag (<see cref="bool"/>), and the entry point name (<see cref="string"/>) is stored here.</description> /// </item> /// <item> /// <term><see cref="GorgonShaderFactory.BinaryShaderByteCode"/></term> /// <description>The compiled shader byte code is stored here and is loaded as a <see cref="byte"/> array.</description> /// </item> /// </list> /// </para> /// </remarks> /// <seealso cref="GorgonChunkFile{T}"/> /// <seealso cref="GorgonChunkFileReader"/> /// <seealso cref="GorgonChunkFileWriter"/> public void SaveToStream(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanWrite) { throw new ArgumentException(Resources.GORGFX_ERR_STREAM_WRITE_ONLY, nameof(stream)); } var chunkFile = new GorgonChunkFileWriter(stream, GorgonShaderFactory.BinaryShaderFileHeader.ChunkID()); try { GorgonBinaryWriter writer = chunkFile.OpenChunk(GorgonShaderFactory.BinaryShaderMetaData); ShaderType shaderType = ShaderType; writer.WriteValue(ref shaderType); writer.WriteValue(ref _isDebug); writer.Write(Name); chunkFile.CloseChunk(); writer = chunkFile.OpenChunk(GorgonShaderFactory.BinaryShaderByteCode); writer.Write(D3DByteCode.Data); } finally { chunkFile.CloseChunk(); } }
/// <summary> /// Function to write the font data to the stream. /// </summary> /// <param name="fontData">The font data to write.</param> /// <param name="stream">The stream to write into.</param> /// <remarks> /// <para> /// Implementors must override this method to write out the font data in the expected format. /// </para> /// </remarks> protected override void OnWriteFontData(GorgonFont fontData, Stream stream) { var fontFile = new GorgonChunkFileWriter(stream, FileHeader.ChunkID()); IGorgonFontInfo fontInfo = fontData.Info; try { fontFile.Open(); GorgonBinaryWriter writer = fontFile.OpenChunk(FontInfoChunk); writer.Write(fontInfo.FontFamilyName); writer.Write(fontInfo.Size); writer.WriteValue(fontInfo.FontHeightMode); writer.WriteValue(fontInfo.FontStyle); writer.Write(fontInfo.DefaultCharacter); writer.Write(string.Join(string.Empty, fontInfo.Characters)); writer.WriteValue(fontInfo.AntiAliasingMode); writer.Write(fontInfo.OutlineColor1.ToARGB()); writer.Write(fontInfo.OutlineColor2.ToARGB()); writer.Write(fontInfo.OutlineSize); writer.Write(fontInfo.PackingSpacing); writer.Write(fontInfo.TextureWidth); writer.Write(fontInfo.TextureHeight); writer.Write(fontInfo.UsePremultipliedTextures); writer.Write(fontInfo.UseKerningPairs); fontFile.CloseChunk(); writer = fontFile.OpenChunk(FontHeightChunk); writer.Write(fontData.FontHeight); writer.Write(fontData.LineHeight); writer.Write(fontData.Ascent); writer.Write(fontData.Descent); fontFile.CloseChunk(); if (fontInfo.Brush != null) { writer = fontFile.OpenChunk(BrushChunk); writer.Write((int)fontInfo.Brush.BrushType); fontInfo.Brush.WriteBrushData(writer); fontFile.CloseChunk(); } if (fontInfo.UseKerningPairs) { WriteKerningValues(fontData, fontFile); } } finally { fontFile.Close(); } }
/// <summary> /// Function to write out the kerning pair information for the font. /// </summary> /// <param name="fontData">The font data to write.</param> /// <param name="fontFile">The font file that is being persisted.</param> private static void WriteKerningValues(GorgonFont fontData, GorgonChunkFileWriter fontFile) { GorgonBinaryWriter writer = fontFile.OpenChunk(KernDataChunk); writer.Write(fontData.KerningPairs.Count); foreach (KeyValuePair <GorgonKerningPair, int> kerningInfo in fontData.KerningPairs) { writer.Write(kerningInfo.Key.LeftCharacter); writer.Write(kerningInfo.Key.RightCharacter); writer.Write(kerningInfo.Value); } fontFile.CloseChunk(); }
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(); } }