/// <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 back the specifics of the font brush data from a file reader.</summary> /// <param name="reader">The reader used to read the brush data.</param> internal override void ReadBrushData(GorgonBinaryReader reader) { WrapMode = (GlyphBrushWrapMode)reader.ReadInt32(); int count = reader.ReadInt32(); Points.Clear(); for (int i = 0; i < count; ++i) { Points.Add(reader.ReadValue <DX.Vector2>()); } BlendFactors.Clear(); count = reader.ReadInt32(); for (int i = 0; i < count; ++i) { BlendFactors.Add(reader.ReadSingle()); } BlendPositions.Clear(); count = reader.ReadInt32(); for (int i = 0; i < count; ++i) { BlendPositions.Add(reader.ReadSingle()); } CenterColor = new GorgonColor(reader.ReadInt32()); CenterPoint = reader.ReadValue <DX.Vector2>(); FocusScales = reader.ReadValue <DX.Vector2>(); count = reader.ReadInt32(); Interpolation.Clear(); for (int i = 0; i < count; ++i) { Interpolation.Add(new GorgonGlyphBrushInterpolator(reader.ReadSingle(), new GorgonColor(reader.ReadInt32()))); } count = reader.ReadInt32(); SurroundColors.Clear(); for (int i = 0; i < count; ++i) { SurroundColors.Add(new GorgonColor(reader.ReadInt32())); } }
/// <summary> /// Function to enumerate the files and directories for a mount point. /// </summary> /// <param name="physicalMountPoint">Mount point being enumerated.</param> /// <param name="mountPoint">Directory to hold the sub directories and files.</param> /// <param name="physicalDirectories">A list of directories in the physical file system (formatted to the virtual file system).</param> /// <param name="physicalFiles">A list of files in the physical file system (formatted to the virtual file system).</param> protected override void Enumerate(string physicalMountPoint, GorgonFileSystemDirectory mountPoint, out string[] physicalDirectories, out PhysicalFileInfo[] physicalFiles) { using (var reader = new GorgonBinaryReader(File.Open(physicalMountPoint, FileMode.Open, FileAccess.Read, FileShare.Read), false)) { // Skip the header. reader.ReadString(); int indexLength = reader.ReadInt32(); byte[] indexData = Decompress(reader.ReadBytes(indexLength)); string xmlData = Encoding.UTF8.GetString(indexData); ParseIndexXML(physicalMountPoint, mountPoint, XDocument.Parse(xmlData, LoadOptions.None), reader.BaseStream.Position, out physicalDirectories, out physicalFiles); } }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPhysicalFileSystemData"/> representing the paths to directories and <see cref="IGorgonPhysicalFileInfo"/> objects under the virtual file system. Each file /// system file and directory is mapped from its <paramref name="physicalLocation"/> on the physical file system to a <paramref name="mountPoint"/> on the virtual file system. For example, if the /// mount point is set to <c>/MyMount/</c>, and the physical location of a file is <c>c:\SourceFileSystem\MyDirectory\MyTextFile.txt</c>, then the returned value should be /// <c>/MyMount/MyDirectory/MyTextFile.txt</c>. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> plug in can override this method to read the list of files from another type of file system, like a Zip file. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> should override this method to read the list of directories and files from another type of file system, like a Zip file. /// The default functionality will only enumerate directories and files from the operating system file system. /// </para> /// </remarks> protected override GorgonPhysicalFileSystemData OnEnumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) { using (var reader = new GorgonBinaryReader(File.Open(physicalLocation, FileMode.Open, FileAccess.Read, FileShare.Read))) { // Skip the header. reader.ReadString(); int indexLength = reader.ReadInt32(); byte[] indexData = Decompress(reader.ReadBytes(indexLength)); string xmlData = Encoding.UTF8.GetString(indexData); var index = XDocument.Parse(xmlData, LoadOptions.None); return(new GorgonPhysicalFileSystemData(EnumerateDirectories(index, mountPoint), EnumerateFiles(index, reader.BaseStream.Position, physicalLocation, mountPoint))); } }
/// <summary>Function to read back the specifics of the font brush data from a file reader.</summary> /// <param name="reader">The reader used to read the brush data.</param> internal override void ReadBrushData(GorgonBinaryReader reader) { Angle = reader.ReadSingle(); ScaleAngle = reader.ReadBoolean(); GammaCorrection = reader.ReadBoolean(); int interpCount = reader.ReadInt32(); if (interpCount == 0) { return; } Interpolation.Clear(); for (int i = 0; i < interpCount; ++i) { Interpolation.Add(new GorgonGlyphBrushInterpolator(reader.ReadSingle(), new GorgonColor(reader.ReadInt32()))); } }
/// <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 a version 1.x Gorgon sprite. /// </summary> /// <param name="sprite">Sprite to fill in with data.</param> /// <param name="reader">Binary reader to use to read in the data.</param> public static void LoadSprite(GorgonSprite sprite, GorgonBinaryReader reader) { Version version; string imageName = string.Empty; sprite.IsV1Sprite = true; reader.BaseStream.Position = 0; string headerVersion = reader.ReadString(); if ((!headerVersion.StartsWith("GORSPR", StringComparison.OrdinalIgnoreCase)) || (headerVersion.Length < 7)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2D_SPRITE_CANNOT_READ_V1_SPRITE); } // Get the version information. switch (headerVersion.ToUpperInvariant()) { case "GORSPR1": version = new Version(1, 0); break; case "GORSPR1.1": version = new Version(1, 1); break; case "GORSPR1.2": version = new Version(1, 2); break; default: throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2D_SPRITE_CANNOT_READ_V1_SPRITE); } // We don't need the sprite name. reader.ReadString(); // Find out if we have an image. if (reader.ReadBoolean()) { bool isRenderTarget = reader.ReadBoolean(); imageName = reader.ReadString(); // We won't be supporting reading render targets from sprites in this version. if (isRenderTarget) { // Skip the target data. reader.ReadInt32(); reader.ReadInt32(); reader.ReadInt32(); reader.ReadBoolean(); reader.ReadBoolean(); } } // We don't use "inherited" values anymore. But we need them because // the file doesn't include inherited data. bool InheritAlphaMaskFunction = reader.ReadBoolean(); bool InheritAlphaMaskValue = reader.ReadBoolean(); bool InheritBlending = reader.ReadBoolean(); bool InheritHorizontalWrapping = reader.ReadBoolean(); bool InheritSmoothing = reader.ReadBoolean(); bool InheritStencilCompare = reader.ReadBoolean(); bool InheritStencilEnabled = reader.ReadBoolean(); bool InheritStencilFailOperation = reader.ReadBoolean(); bool InheritStencilMask = reader.ReadBoolean(); bool InheritStencilPassOperation = reader.ReadBoolean(); bool InheritStencilReference = reader.ReadBoolean(); bool InheritStencilZFailOperation = reader.ReadBoolean(); bool InheritVerticalWrapping = reader.ReadBoolean(); bool InheritDepthBias = true; bool InheritDepthTestFunction = true; bool InheritDepthWriteEnabled = true; // Get version 1.1 fields. if ((version.Major == 1) && (version.Minor >= 1)) { InheritDepthBias = reader.ReadBoolean(); InheritDepthTestFunction = reader.ReadBoolean(); InheritDepthWriteEnabled = reader.ReadBoolean(); } // Get the size of the sprite. sprite.Size = new Vector2(reader.ReadSingle(), reader.ReadSingle()); // Older versions of the sprite object used pixel space for their texture coordinates. We will have to // fix up these coordinates into texture space once we have a texture loaded. At this point, there's no guarantee // that the texture was loaded safely, so we'll have to defer it until later. // Also, older versions used the size the determine the area on the texture to cover. So use the size to // get the texture bounds. var textureOffset = new Vector2(reader.ReadSingle(), reader.ReadSingle()); sprite.TextureOffset = textureOffset; sprite.TextureSize = sprite.Size; // Read the anchor. sprite.Anchor = new Vector2(reader.ReadSingle(), reader.ReadSingle()); // Get vertex offsets. sprite.SetCornerOffset(RectangleCorner.UpperLeft, new Vector2(reader.ReadSingle(), reader.ReadSingle())); sprite.SetCornerOffset(RectangleCorner.UpperRight, new Vector2(reader.ReadSingle(), reader.ReadSingle())); sprite.SetCornerOffset(RectangleCorner.LowerRight, new Vector2(reader.ReadSingle(), reader.ReadSingle())); sprite.SetCornerOffset(RectangleCorner.LowerLeft, new Vector2(reader.ReadSingle(), reader.ReadSingle())); // Get vertex colors. sprite.SetCornerColor(RectangleCorner.UpperLeft, new GorgonColor(reader.ReadInt32())); sprite.SetCornerColor(RectangleCorner.UpperRight, new GorgonColor(reader.ReadInt32())); sprite.SetCornerColor(RectangleCorner.LowerLeft, new GorgonColor(reader.ReadInt32())); sprite.SetCornerColor(RectangleCorner.LowerRight, new GorgonColor(reader.ReadInt32())); // Skip shader information. Version 1.0 had shader information attached to the sprite. if ((version.Major == 1) && (version.Minor < 1)) { if (reader.ReadBoolean()) { reader.ReadString(); reader.ReadBoolean(); if (reader.ReadBoolean()) { reader.ReadString(); } } } // We no longer have an alpha mask function. if (!InheritAlphaMaskFunction) { reader.ReadInt32(); } if (!InheritAlphaMaskValue) { // Direct 3D 9 used a value from 0..255 for alpha masking, we use // a scalar value so convert to a scalar. sprite.AlphaTestValues = new GorgonRangeF(0.0f, reader.ReadInt32() / 255.0f); } // Set the blending mode. if (!InheritBlending) { sprite.Blending.SourceBlend = ConvertBlendOpToBlendType(reader.ReadInt32()); sprite.Blending.DestinationBlend = ConvertBlendOpToBlendType(reader.ReadInt32()); // Skip the blending mode, this gets detected automatically now. reader.ReadInt32(); } // Get alpha blending mode. if ((version.Major == 1) && (version.Minor >= 2)) { sprite.Blending.DestinationAlphaBlend = ConvertBlendOpToBlendType(reader.ReadInt32()); sprite.Blending.SourceAlphaBlend = ConvertBlendOpToBlendType(reader.ReadInt32()); } // Get horizontal wrapping mode. if (!InheritHorizontalWrapping) { sprite.TextureSampler.HorizontalWrapping = ConvertImageAddressToTextureAddress(reader.ReadInt32()); } // Get smoothing mode. if (!InheritSmoothing) { sprite.TextureSampler.TextureFilter = ConvertSmoothingToFilter(reader.ReadInt32()); } // Get stencil stuff. if (!InheritStencilCompare) { sprite.DepthStencil.FrontFace.ComparisonOperator = ConvertCompare(reader.ReadInt32()); } if (!InheritStencilEnabled) { // We don't enable stencil in the same way anymore, so skip this value. reader.ReadBoolean(); } if (!InheritStencilFailOperation) { sprite.DepthStencil.FrontFace.FailOperation = ConvertStencilOp(reader.ReadInt32()); } if (!InheritStencilMask) { sprite.DepthStencil.StencilReadMask = (byte)(reader.ReadInt32() & 0xFF); } if (!InheritStencilPassOperation) { sprite.DepthStencil.FrontFace.PassOperation = ConvertStencilOp(reader.ReadInt32()); } if (!InheritStencilReference) { sprite.DepthStencil.StencilReference = reader.ReadInt32(); } if (!InheritStencilZFailOperation) { sprite.DepthStencil.FrontFace.DepthFailOperation = ConvertStencilOp(reader.ReadInt32()); } // Get vertical wrapping mode. if (!InheritVerticalWrapping) { sprite.TextureSampler.VerticalWrapping = ConvertImageAddressToTextureAddress(reader.ReadInt32()); } // Get depth info. if ((version.Major == 1) && (version.Minor >= 1)) { if (!InheritDepthBias) { // Depth bias values are quite different on D3D9 than they are on D3D11, so skip this. reader.ReadSingle(); } if (!InheritDepthTestFunction) { sprite.DepthStencil.DepthComparison = ConvertCompare(reader.ReadInt32()); } if (!InheritDepthWriteEnabled) { sprite.DepthStencil.IsDepthWriteEnabled = reader.ReadBoolean(); } sprite.TextureSampler.BorderColor = new GorgonColor(reader.ReadInt32()); } // Get flipped flags. sprite.HorizontalFlip = reader.ReadBoolean(); sprite.VerticalFlip = reader.ReadBoolean(); // Bind the texture (if we have one bound to this sprite) if it's already loaded, otherwise defer it. if (string.IsNullOrEmpty(imageName)) { return; } sprite.DeferredTextureName = imageName; }
/// <summary>Function to read back the specifics of the font brush data from a file reader.</summary> /// <param name="reader">The reader used to read the brush data.</param> internal override void ReadBrushData(GorgonBinaryReader reader) { HatchStyle = (GlyphBrushHatchStyle)reader.ReadInt32(); ForegroundColor = new GorgonColor(reader.ReadInt32()); BackgroundColor = new GorgonColor(reader.ReadInt32()); }
/// <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(); } }
/// <summary>Function to read back the specifics of the font brush data from a file reader.</summary> /// <param name="reader">The reader used to read the brush data.</param> internal override void ReadBrushData(GorgonBinaryReader reader) => Color = new GorgonColor(reader.ReadInt32());
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(); } }