using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.IO; namespace FSO.Files.Utils { public static class CurLoader { public static MouseCursor LoadMonoCursor(GraphicsDevice gd, Stream stream) { var cur = LoadCursor(gd, stream); return MouseCursor.FromTexture2D(cur.Item1, cur.Item2.X, cur.Item2.Y); } public static Tuple LoadCursor(GraphicsDevice gd, Stream stream) { using (var io = new BinaryReader(stream)) { //little endian var tempbmp = new MemoryStream(); var outIO = new BinaryWriter(tempbmp); var reserved = io.ReadInt16(); var type = io.ReadInt16(); if (type != 2) throw new Exception("Not a cursor!"); var images = io.ReadInt16(); //currently discard extra images... //read first image var width = io.ReadByte(); var height = io.ReadByte(); var colors = io.ReadByte(); var reserved2 = io.ReadByte(); var xOffset = io.ReadInt16(); var yOffset = io.ReadInt16(); var size = io.ReadInt32(); var offset = io.ReadInt32(); stream.Seek(offset - 22, SeekOrigin.Current); //ok... now write the bitmap data to a fake bitmap outIO.Write(new char[] { 'B', 'M' }); outIO.Write(size + 14); //size, plus header outIO.Write(0); outIO.Write(14); var data = new byte[size]; stream.Read(data, 0, size); outIO.Write(data); tempbmp.Seek(0, SeekOrigin.Begin); var tex = ImageLoader.FromStream(gd, tempbmp); //our mask is on top. the image is on bottom. var odata = new byte[tex.Width * tex.Height * 4]; tex.GetData(odata); var ndata = new byte[tex.Width * tex.Height * 2]; var limit = ndata.Length; for (int i=0; i< limit; i+=4) { var j = i + limit; ndata[i] = (byte)((~odata[i]) & odata[j]); ndata[i+1] = ndata[i]; ndata[i+2] = ndata[i]; ndata[i+3] = (byte)(~odata[i]); } var oTex = new Texture2D(gd, width, height); oTex.SetData(ndata); tex.Dispose(); return new Tuple(oTex, new Point(xOffset, yOffset)); } } } }