/// <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 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 copy the contents of a stream into a <see cref="GorgonNativeBuffer{T}"/>. /// </summary> /// <typeparam name="T">The type of value in the buffer. Must be an unmanaged value type.</typeparam> /// <param name="stream">The stream to read from.</param> /// <param name="count">[Optional] The maximum number of items to read from the stream.</param> /// <returns>A <see cref="GorgonNativeBuffer{T}"/> containing the contents of the stream.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is <b>null</b>.</exception> /// <exception cref="EndOfStreamException">Thrown when the <paramref name="stream"/> is at its end.</exception> /// <exception cref="IOException">Thrown when the <paramref name="stream"/> is write only.</exception> public static GorgonNativeBuffer <T> ToNativeBuffer <T>(this Stream stream, int?count = null) where T : unmanaged { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (stream.Position == stream.Length) { throw new EndOfStreamException(); } if (!stream.CanRead) { throw new IOException(Resources.GOR_ERR_STREAM_IS_WRITEONLY); } int typeSize = Unsafe.SizeOf <T>(); if (count == null) { if (typeSize == 1) { count = (int)(stream.Length - stream.Position); } else { count = (int)((stream.Length - stream.Position) / typeSize); } } var result = new GorgonNativeBuffer <T>(count.Value); using (var reader = new GorgonBinaryReader(stream, true)) { for (int i = 0; i < count.Value; ++i) { if (stream.Position + typeSize >= stream.Length) { break; } reader.ReadValue(out result[i]); } } return(result); }
/// <summary> /// Function to determine if this codec can read the file or not. /// </summary> /// <param name="stream">Stream used to read the file information.</param> /// <returns> /// TRUE if the codec can read the file, FALSE if not. /// </returns> /// <remarks> /// This is the method we'll use to determine if the data in the stream can actually be read by our codec. Typically this is done by a "magic number" consisting of a set of bytes /// that identify the data as the type we're expecting. To retrieve the magic number we'll read in the meta data for the image, which may not seem efficient, but it gives us the /// ability to also check to ensure that the image stream contains enough information about the image to actually load it by comparing the size of the meta data in the stream with /// the required meta data size. /// <para> /// When overloading this method, the implementor should remember to reset the stream position back to the original position when they are done reading the data. Failure to do so /// may cause undesirable results. /// </para> /// </remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.IO.IOException">Thrown when the <paramref name="stream"/> is write-only or if the stream cannot perform seek operations.</exception> /// <exception cref="System.IO.EndOfStreamException">Thrown when an attempt to read beyond the end of the stream is made.</exception> public override bool IsReadable(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { throw new IOException("The stream is write only."); } if (!stream.CanSeek) { throw new IOException("Stream cannot perform seek operations."); } if (stream.Position + TvHeader.SizeInBytes >= stream.Length) { throw new EndOfStreamException(); } // Remember the stream position. // If we fail to do this then the stream will be offset when we return and could cause corruption. long position = stream.Position; GorgonBinaryReader reader = null; try { // Using the GorgonBinaryReader, we can pull in the data we need. reader = new GorgonBinaryReader(stream, true); // Retrieve our magic number. var header = reader.ReadValue <TvHeader>(); // Ensure that the image size is valid and that the magic numbers match up. return(header.Width > 0 && header.Height > 0 && header.MagicValueData == MagicValue); } finally { if (reader != null) { reader.Dispose(); } // Restore the stream to its original placement. stream.Position = position; } }
/// <summary> /// Function to read the meta data for the image. /// </summary> /// <param name="stream">Stream containing the image data.</param> /// <returns>An image settings object containing information about the image.</returns> private static IImageSettings ReadMetaData(Stream stream) { if (!stream.CanRead) { throw new ArgumentException(@"Stream is write only.", "stream"); } if (stream.Position + TvHeader.SizeInBytes >= stream.Length) { throw new EndOfStreamException(); } // We only support 2D images with the tv format. var settings = new GorgonTexture2DSettings(); TvHeader header; // Load the header for the image. using (var reader = new GorgonBinaryReader(stream, true)) { header = reader.ReadValue <TvHeader>(); } // Ensure we've got the correct data. if (header.MagicValueData != MagicValue) { throw new ArgumentException(@"The image data is not a tv image.", "stream"); } // Ensure the width/height are valid. if ((header.Width < 0) || (header.Height < 0)) { throw new ArgumentException(@"The image in this stream has an invalid width/height.", "stream"); } settings.Width = header.Width; settings.Height = header.Height; settings.Format = BufferFormat.R8G8B8A8_UIntNormal; return(settings); }
/// <summary> /// Function to read in the TGA header from a stream. /// </summary> /// <param name="reader">The reader used to read the stream containing the data.</param> /// <param name="conversionFlags">Flags for conversion.</param> /// <returns>New image settings.</returns> private static IGorgonImageInfo ReadHeader(GorgonBinaryReader reader, out TGAConversionFlags conversionFlags) { conversionFlags = TGAConversionFlags.None; // Get the header for the file. TgaHeader header = reader.ReadValue <TgaHeader>(); if ((header.ColorMapType != 0) || (header.ColorMapLength != 0) || (header.Width <= 0) || (header.Height <= 0) || ((header.Descriptor & TgaDescriptor.Interleaved2Way) == TgaDescriptor.Interleaved2Way) || ((header.Descriptor & TgaDescriptor.Interleaved4Way) == TgaDescriptor.Interleaved4Way)) { throw new NotSupportedException(Resources.GORIMG_ERR_TGA_TYPE_NOT_SUPPORTED); } BufferFormat pixelFormat = BufferFormat.Unknown; switch (header.ImageType) { case TgaImageType.TrueColor: case TgaImageType.TrueColorRLE: switch (header.BPP) { case 16: pixelFormat = BufferFormat.B5G5R5A1_UNorm; break; case 24: case 32: pixelFormat = BufferFormat.R8G8B8A8_UNorm; if (header.BPP == 24) { conversionFlags |= TGAConversionFlags.Expand; } break; } if (header.ImageType == TgaImageType.TrueColorRLE) { conversionFlags |= TGAConversionFlags.RLE; } break; case TgaImageType.BlackAndWhite: case TgaImageType.BlackAndWhiteRLE: if (header.BPP == 8) { pixelFormat = BufferFormat.R8_UNorm; } else { throw new IOException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, header.ImageType)); } if (header.ImageType == TgaImageType.BlackAndWhiteRLE) { conversionFlags |= TGAConversionFlags.RLE; } break; default: throw new IOException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, header.ImageType)); } var settings = new GorgonImageInfo(ImageType.Image2D, pixelFormat) { MipCount = 1, ArrayCount = 1, Width = header.Width, Height = header.Height }; if ((header.Descriptor & TgaDescriptor.InvertX) == TgaDescriptor.InvertX) { conversionFlags |= TGAConversionFlags.InvertX; } if ((header.Descriptor & TgaDescriptor.InvertY) == TgaDescriptor.InvertY) { conversionFlags |= TGAConversionFlags.InvertY; } if (header.IDLength <= 0) { return(settings); } // Skip these bytes. for (int i = 0; i < header.IDLength; i++) { reader.ReadByte(); } return(settings); }
/// <summary> /// Function to determine if this codec can read the image data within the stream or not. /// </summary> /// <param name="stream">The stream that is used to read the image data.</param> /// <returns><b>true</b> if the codec can read the file, <b>false</b> if not.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is <b>null</b>.</exception> /// <exception cref="IOException">Thrown when the <paramref name="stream"/> is write-only or if the stream cannot perform seek operations.</exception> public override bool IsReadable(Stream stream) { TgaHeader header; long position = 0; if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead) { throw new IOException(Resources.GORIMG_ERR_STREAM_IS_WRITEONLY); } if (!stream.CanSeek) { throw new IOException(Resources.GORIMG_ERR_STREAM_CANNOT_SEEK); } if (stream.Length - stream.Position < Unsafe.SizeOf <TgaHeader>()) { return(false); } try { position = stream.Position; var reader = new GorgonBinaryReader(stream, true); header = reader.ReadValue <TgaHeader>(); } finally { stream.Position = position; } if ((header.ColorMapType != 0) || (header.ColorMapLength != 0)) { return(false); } if ((header.Descriptor & (TgaDescriptor.Interleaved2Way | TgaDescriptor.Interleaved4Way)) != 0) { return(false); } if ((header.Width <= 0) || (header.Height <= 0)) { return(false); } #pragma warning disable IDE0046 // Convert to conditional expression if ((header.ImageType != TgaImageType.TrueColor) && (header.ImageType != TgaImageType.TrueColorRLE) && (header.ImageType != TgaImageType.BlackAndWhite) && (header.ImageType != TgaImageType.BlackAndWhiteRLE)) { return(false); } #pragma warning restore IDE0046 // Convert to conditional expression return(((header.ImageType != TgaImageType.BlackAndWhite) && (header.ImageType != TgaImageType.BlackAndWhiteRLE)) || (header.BPP == 8)); }