support for .NET framework 3.5

Still have bugs
This commit is contained in:
NaBian committed 2019-01-21 00:43:10 +08:00
1 parent 5878039e21
commit 7d6b491f25
704 files changed
+48273 -33

No files matched your search

@@ -0,0 +1,271 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using HandyControl.Tools;
namespace HandyControl.Data
{
// ReSharper disable once InconsistentNaming
internal class GPStream : ExternDllHelper.IStream
{
protected Stream DataStream;
// to support seeking ahead of the stream length...
long _virtualPosition = -1;
internal GPStream(Stream stream)
{
if (!stream.CanSeek)
{
const int readBlock = 256;
var bytes = new byte[readBlock];
int readLen;
var current = 0;
do
{
if (bytes.Length < current + readBlock)
{
var newData = new byte[bytes.Length * 2];
Array.Copy(bytes, newData, bytes.Length);
bytes = newData;
}
readLen = stream.Read(bytes, current, readBlock);
current += readLen;
} while (readLen != 0);
DataStream = new MemoryStream(bytes);
}
else
{
DataStream = stream;
}
}
private void ActualizeVirtualPosition()
{
if (_virtualPosition == -1) return;
if (_virtualPosition > DataStream.Length)
DataStream.SetLength(_virtualPosition);
DataStream.Position = _virtualPosition;
_virtualPosition = -1;
}
public virtual ExternDllHelper.IStream Clone()
{
NotImplemented();
return null;
}
public virtual void Commit(int grfCommitFlags)
{
DataStream.Flush();
// Extend the length of the file if needed.
ActualizeVirtualPosition();
}
[
UIPermission(SecurityAction.Demand, Window = UIPermissionWindow.AllWindows),
SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
]
public virtual long CopyTo(ExternDllHelper.IStream pstm, long cb, long[] pcbRead)
{
const int bufsize = 4096;
var buffer = Marshal.AllocHGlobal(bufsize);
if (buffer == IntPtr.Zero) throw new OutOfMemoryException();
long written = 0;
try
{
while (written < cb)
{
var toRead = bufsize;
if (written + toRead > cb) toRead = (int)(cb - written);
var read = Read(buffer, toRead);
if (read == 0) break;
if (pstm.Write(buffer, read) != read)
{
throw EFail("Wrote an incorrect number of bytes");
}
written += read;
}
}
finally
{
Marshal.FreeHGlobal(buffer);
}
if (pcbRead != null && pcbRead.Length > 0)
{
pcbRead[0] = written;
}
return written;
}
public virtual Stream GetDataStream()
{
return DataStream;
}
public virtual void LockRegion(long libOffset, long cb, int dwLockType)
{
}
protected static ExternalException EFail(string msg)
{
throw new ExternalException(msg, ExternDllHelper.E_FAIL);
}
protected static void NotImplemented()
{
throw new ExternalException("NotImplemented");
}
public virtual int Read(IntPtr buf, int length)
{
var buffer = new byte[length];
var count = Read(buffer, length);
Marshal.Copy(buffer, 0, buf, length);
return count;
}
public virtual int Read(byte[] buffer, int length)
{
ActualizeVirtualPosition();
return DataStream.Read(buffer, 0, length);
}
public virtual void Revert()
{
NotImplemented();
}
public virtual long Seek(long offset, int origin)
{
var pos = _virtualPosition;
if (_virtualPosition == -1)
{
pos = DataStream.Position;
}
var len = DataStream.Length;
switch (origin)
{
case ExternDllHelper.StreamConsts.STREAM_SEEK_SET:
if (offset <= len)
{
DataStream.Position = offset;
_virtualPosition = -1;
}
else
{
_virtualPosition = offset;
}
break;
case ExternDllHelper.StreamConsts.STREAM_SEEK_END:
if (offset <= 0)
{
DataStream.Position = len + offset;
_virtualPosition = -1;
}
else
{
_virtualPosition = len + offset;
}
break;
case ExternDllHelper.StreamConsts.STREAM_SEEK_CUR:
if (offset + pos <= len)
{
DataStream.Position = pos + offset;
_virtualPosition = -1;
}
else
{
_virtualPosition = offset + pos;
}
break;
}
return _virtualPosition != -1 ? _virtualPosition : DataStream.Position;
}
public virtual void SetSize(long value)
{
DataStream.SetLength(value);
}
public void Stat(IntPtr pstatstg, int grfStatFlag)
{
var stats = new STATSTG {cbSize = DataStream.Length};
Marshal.StructureToPtr(stats, pstatstg, true);
}
public virtual void UnlockRegion(long libOffset, long cb, int dwLockType)
{
}
public virtual int Write(IntPtr buf, int length)
{
var buffer = new byte[length];
Marshal.Copy(buf, buffer, 0, length);
return Write(buffer, length);
}
public virtual int Write(byte[] buffer, int length)
{
ActualizeVirtualPosition();
DataStream.Write(buffer, 0, length);
return length;
}
[StructLayout(LayoutKind.Sequential)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class STATSTG
{
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
public IntPtr pwcsName = IntPtr.Zero;
public int type;
[MarshalAs(UnmanagedType.I8)]
public long cbSize;
[MarshalAs(UnmanagedType.I8)]
public long mtime;
[MarshalAs(UnmanagedType.I8)]
public long ctime;
[MarshalAs(UnmanagedType.I8)]
public long atime;
[MarshalAs(UnmanagedType.I4)]
public int grfMode;
[MarshalAs(UnmanagedType.I4)]
public int grfLocksSupported;
public int clsid_data1;
[MarshalAs(UnmanagedType.I2)]
public short clsid_data2;
[MarshalAs(UnmanagedType.I2)]
public short clsid_data3;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b0;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b1;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b2;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b3;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b4;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b5;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b6;
[MarshalAs(UnmanagedType.U1)]
public byte clsid_b7;
[MarshalAs(UnmanagedType.I4)]
public int grfStateBits;
[MarshalAs(UnmanagedType.I4)]
public int reserved;
}
}
}
@@ -0,0 +1,29 @@
using System;
namespace HandyControl.Data
{
internal class GifFrameDimension
{
public GifFrameDimension(Guid guid) => Guid = guid;
public Guid Guid { get; }
public static GifFrameDimension Time { get; } = new GifFrameDimension(new Guid("{6aedbd6d-3fb5-418a-83a6-7f45229dc872}"));
public static GifFrameDimension Resolution { get; } = new GifFrameDimension(new Guid("{84236f7b-3bd3-428f-8dab-4ea1439ca315}"));
public static GifFrameDimension Page { get; } = new GifFrameDimension(new Guid("{7462dc86-6180-4c7e-8e3f-ee7333a7a483}"));
public override bool Equals(object o) => o is GifFrameDimension format && Guid == format.Guid;
public override int GetHashCode() => Guid.GetHashCode();
public override string ToString()
{
if (Equals(this, Time)) return "Time";
if (Equals(this, Resolution)) return "Resolution";
if (Equals(this, Page)) return "Page";
return "[FrameDimension: " + Guid + "]";
}
}
}
@@ -0,0 +1,97 @@
using System;
using HandyControl.Controls;
namespace HandyControl.Data
{
public class GifImageInfo
{
private const int PropertyTagFrameDelay = 0x5100;
private int _frame;
private readonly int[] _frameDelay;
public int FrameCount { get; }
internal GifImage Image { get; }
public bool Animated { get; }
public EventHandler FrameChangedHandler { get; set; }
internal int FrameTimer { get; set; }
public bool FrameDirty { get; private set; }
public int Frame
{
get => _frame;
set
{
if (_frame != value)
{
if (value < 0 || value >= FrameCount)
{
throw new ArgumentException("InvalidFrame");
}
if (Animated)
{
_frame = value;
FrameDirty = true;
OnFrameChanged(EventArgs.Empty);
}
}
}
}
public GifImageInfo(GifImage image)
{
Image = image;
Animated = ImageAnimator.CanAnimate(image);
if (Animated)
{
FrameCount = image.GetFrameCount(GifFrameDimension.Time);
var frameDelayItem = image.GetPropertyItem(PropertyTagFrameDelay);
// If the image does not have a frame delay, we just return 0.
//
if (frameDelayItem != null)
{
// Convert the frame delay from byte[] to int
//
var values = frameDelayItem.Value;
_frameDelay = new int[FrameCount];
for (int i = 0; i < FrameCount; ++i)
{
_frameDelay[i] = values[i * 4] + 256 * values[i * 4 + 1] + 256 * 256 * values[i * 4 + 2] + 256 * 256 * 256 * values[i * 4 + 3];
}
}
}
else
{
FrameCount = 1;
}
if (_frameDelay == null)
{
_frameDelay = new int[FrameCount];
}
}
public int FrameDelay(int frame) => _frameDelay[frame];
internal void UpdateFrame()
{
if (FrameDirty)
{
Image.SelectActiveFrame(GifFrameDimension.Time, Frame);
FrameDirty = false;
}
}
protected void OnFrameChanged(EventArgs e) => FrameChangedHandler?.Invoke(Image, e);
}
}
@@ -0,0 +1,13 @@
namespace HandyControl.Data
{
public class GifPropertyItem
{
public int Id { get; set; }
public int Len { get; set; }
public short Type { get; set; }
public byte[] Value { get; set; }
}
}
@@ -0,0 +1,114 @@
using System;
using System.Runtime.InteropServices;
using HandyControl.Tools;
namespace HandyControl.Data
{
[StructLayout(LayoutKind.Sequential)]
public class GifPropertyItemInternal : IDisposable
{
public int id;
public int len;
public short type;
public IntPtr value = IntPtr.Zero;
internal GifPropertyItemInternal()
{
}
public byte[] Value
{
get
{
if (len == 0)
return null;
var bytes = new byte[len];
Marshal.Copy(value,
bytes,
0,
len);
return bytes;
}
}
public void Dispose()
{
Dispose(true);
}
~GifPropertyItemInternal()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (value != IntPtr.Zero)
{
Marshal.FreeHGlobal(value);
value = IntPtr.Zero;
}
if (disposing)
GC.SuppressFinalize(this);
}
internal static GifPropertyItemInternal ConvertFromPropertyItem(GifPropertyItem propItem)
{
var propItemInternal = new GifPropertyItemInternal
{
id = propItem.Id,
len = 0,
type = propItem.Type
};
var propItemValue = propItem.Value;
if (propItemValue != null)
{
var length = propItemValue.Length;
propItemInternal.len = length;
propItemInternal.value = Marshal.AllocHGlobal(length);
Marshal.Copy(propItemValue, 0, propItemInternal.value, length);
}
return propItemInternal;
}
internal static GifPropertyItem[] ConvertFromMemory(IntPtr propdata, int count)
{
var props = new GifPropertyItem[count];
for (var i = 0; i < count; i++)
{
GifPropertyItemInternal propcopy = null;
try
{
propcopy = (GifPropertyItemInternal) ExternDllHelper.PtrToStructure(propdata,
typeof(GifPropertyItemInternal));
props[i] = new GifPropertyItem
{
Id = propcopy.id,
Len = propcopy.len,
Type = propcopy.type,
Value = propcopy.Value
};
// this calls Marshal.Copy and creates a copy of the original memory into a byte array.
propcopy.value = IntPtr.Zero; // we dont actually own this memory so dont free it.
}
finally
{
propcopy?.Dispose();
}
propdata = (IntPtr) ((long) propdata + Marshal.SizeOf(typeof(GifPropertyItemInternal)));
}
return props;
}
}
}