Browse Source

Merge branch 'master' into scenegraph

Conflicts:
	src/Skia/Avalonia.Skia/DrawingContextImpl.cs
scenegraph-after-breakage
Steven Kirk 9 years ago
parent
commit
bf6b9c1e7f
  1. 5
      src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
  2. 18
      src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
  3. 1
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  4. 5
      src/Avalonia.Visuals/Platform/ExportRenderingSubsystemAttribute.cs
  5. 7
      src/Avalonia.Visuals/Platform/IModuleEnvironmentChecker.cs
  6. 6
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  7. 1
      src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
  8. 3
      src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs
  9. 15
      src/Windows/Avalonia.Direct2D1/WindowsVersionChecker.cs
  10. 2
      src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj
  11. 197
      src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs
  12. 128
      src/Windows/Avalonia.Win32.NetStandard/Gdip.cs
  13. 30
      src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs
  14. 16
      src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs

5
src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs

@ -9,16 +9,19 @@ namespace Avalonia.Platform
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class ExportWindowingSubsystemAttribute : Attribute
{
public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType, string initializationMethod)
public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType,
string initializationMethod, Type environmentChecker = null)
{
Name = name;
InitializationType = initializationType;
InitializationMethod = initializationMethod;
EnvironmentChecker = environmentChecker;
RequiredOS = requiredRuntimePlatform;
Priority = priority;
}
public string InitializationMethod { get; private set; }
public Type EnvironmentChecker { get; }
public Type InitializationType { get; private set; }
public string Name { get; private set; }
public int Priority { get; private set; }

18
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@ -31,6 +31,20 @@ namespace Avalonia
Instance = app;
}
bool CheckEnvironment(Type checkerType)
{
if (checkerType == null)
return true;
try
{
return ((IModuleEnvironmentChecker) Activator.CreateInstance(checkerType)).IsCompatible;
}
catch
{
return false;
}
}
/// <summary>
/// Instructs the <see cref="AppBuilder"/> to use the best settings for the platform.
/// </summary>
@ -43,13 +57,13 @@ namespace Avalonia
var windowingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>()
where attribute.RequiredOS == os
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
orderby attribute.Priority ascending
select attribute).First();
var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>()
where attribute.RequiredOS == os
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
where attribute.RequiresWindowingSubsystem == null
|| attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name
orderby attribute.Priority ascending

1
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -122,6 +122,7 @@
<Compile Include="Rendering\DirtyVisuals.cs" />
<Compile Include="Rendering\DisplayDirtyRect.cs" />
<Compile Include="Rendering\DisplayDirtyRects.cs" />
<Compile Include="Platform\IModuleEnvironmentChecker.cs" />
<Compile Include="Rendering\IRenderer.cs" />
<Compile Include="Rendering\IRendererFactory.cs" />
<Compile Include="Rendering\IRenderLoop.cs" />

5
src/Avalonia.Visuals/Platform/ExportRenderingSubsystemAttribute.cs

@ -9,16 +9,19 @@ namespace Avalonia.Platform
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class ExportRenderingSubsystemAttribute : Attribute
{
public ExportRenderingSubsystemAttribute(OperatingSystemType requiredOS, int priority, string name, Type initializationType, string initializationMethod)
public ExportRenderingSubsystemAttribute(OperatingSystemType requiredOS, int priority, string name, Type initializationType, string initializationMethod,
Type environmentChecker = null)
{
Name = name;
InitializationType = initializationType;
InitializationMethod = initializationMethod;
EnvironmentChecker = environmentChecker;
RequiredOS = requiredOS;
Priority = priority;
}
public string InitializationMethod { get; private set; }
public Type EnvironmentChecker { get; }
public Type InitializationType { get; private set; }
public string Name { get; private set; }
public int Priority { get; private set; }

7
src/Avalonia.Visuals/Platform/IModuleEnvironmentChecker.cs

@ -0,0 +1,7 @@
namespace Avalonia.Platform
{
public interface IModuleEnvironmentChecker
{
bool IsCompatible { get; }
}
}

6
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -19,10 +19,12 @@ namespace Avalonia.Skia
public DrawingContextImpl(SKCanvas canvas, Matrix? postTransform = null, params IDisposable[] disposables)
{
if (_postTransform.HasValue && !_postTransform.Value.IsIdentity)
if (postTransform.HasValue && !postTransform.Value.IsIdentity)
_postTransform = postTransform;
_disposables = disposables;
Canvas = canvas;
Canvas.Clear();
Transform = Matrix.Identity;
}
public void Clear(Color color)
@ -362,7 +364,7 @@ namespace Avalonia.Skia
Canvas.Restore();
}
private Matrix _currentTransform = Matrix.Identity;
private Matrix _currentTransform;
public Matrix Transform
{

1
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@ -97,6 +97,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="SwapChainRenderTarget.cs" />
<Compile Include="WindowsVersionChecker.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />

3
src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs

@ -6,5 +6,6 @@ using Avalonia.Platform;
using Avalonia.Direct2D1;
[assembly: AssemblyTitle("Avalonia.Direct2D1")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize))]
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize),
typeof(WindowsVersionChecker))]

15
src/Windows/Avalonia.Direct2D1/WindowsVersionChecker.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Direct2D1
{
class WindowsVersionChecker : IModuleEnvironmentChecker
{
//Direct2D backend doesn't work with Win7 anymore
public bool IsCompatible => Environment.OSVersion.Version >= new Version(6, 2);
}
}

2
src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj

@ -75,6 +75,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="ComStreamWrapper.cs" />
<Compile Include="Gdip.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="NativeWin32Platform.cs" />
<Compile Include="Win32Exception.cs" />

197
src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs

@ -0,0 +1,197 @@
//
// System.Drawing.ComIStreamWrapper.cs
//
// Author:
// Kornél Pál <http://www.kornelpal.hu/>
//
// Copyright (C) 2005-2008 Kornél Pál
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;
namespace Avalonia.Win32
{
// Stream to IStream wrapper for COM interop
internal sealed class ComIStreamWrapper : IStream
{
private const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001);
private readonly Stream baseStream;
private long position = -1;
internal ComIStreamWrapper(Stream stream)
{
baseStream = stream;
}
private void SetSizeToPosition()
{
if (position != -1)
{
if (position > baseStream.Length)
baseStream.SetLength(position);
baseStream.Position = position;
position = -1;
}
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int read = 0;
if (cb != 0)
{
SetSizeToPosition();
read = baseStream.Read(pv, 0, cb);
}
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, read);
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
if (cb != 0)
{
SetSizeToPosition();
baseStream.Write(pv, 0, cb);
}
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt32(pcbWritten, cb);
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long length = baseStream.Length;
long newPosition;
switch ((SeekOrigin)dwOrigin)
{
case SeekOrigin.Begin:
newPosition = dlibMove;
break;
case SeekOrigin.Current:
if (position == -1)
newPosition = baseStream.Position + dlibMove;
else
newPosition = position + dlibMove;
break;
case SeekOrigin.End:
newPosition = length + dlibMove;
break;
default:
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
if (newPosition > length)
position = newPosition;
else
{
baseStream.Position = newPosition;
position = -1;
}
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, newPosition);
}
public void SetSize(long libNewSize)
{
baseStream.SetLength(libNewSize);
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
byte[] buffer;
long written = 0;
int read;
int count;
if (cb != 0)
{
if (cb < 4096)
count = (int)cb;
else
count = 4096;
buffer = new byte[count];
SetSizeToPosition();
while (true)
{
if ((read = baseStream.Read(buffer, 0, count)) == 0)
break;
pstm.Write(buffer, read, IntPtr.Zero);
written += read;
if (written >= cb)
break;
if (cb - written < 4096)
count = (int)(cb - written);
}
}
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt64(pcbRead, written);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt64(pcbWritten, written);
}
public void Commit(int grfCommitFlags)
{
baseStream.Flush();
SetSizeToPosition();
}
public void Revert()
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void Stat(out STATSTG pstatstg, int grfStatFlag)
{
pstatstg = new STATSTG();
pstatstg.cbSize = baseStream.Length;
}
public void Clone(out IStream ppstm)
{
ppstm = null;
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
}
}

128
src/Windows/Avalonia.Win32.NetStandard/Gdip.cs

@ -0,0 +1,128 @@
//
// Code copy-pasted from from Mono / System.Drawing.*.cs
// Original license below:
//
// Authors:
// Alexandre Pigolkine (pigolkine@gmx.de)
// Jordi Mas (jordi@ximian.com)
// Sanjay Gupta (gsanjay@novell.com)
// Ravindra (rkumar@novell.com)
// Peter Dennis Bartok (pbartok@novell.com)
// Sebastien Pouliot <sebastien@ximian.com>
//
//
// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Win32
{
static class Gdip
{
public enum Status
{
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
ProfileNotFound = 21
}
[StructLayout(LayoutKind.Sequential)]
internal struct GdiplusStartupInput
{
// internalted to silent compiler
internal uint GdiplusVersion;
internal IntPtr DebugEventCallback;
internal int SuppressBackgroundThread;
internal int SuppressExternalCodecs;
internal static GdiplusStartupInput MakeGdiplusStartupInput()
{
GdiplusStartupInput result = new GdiplusStartupInput();
result.GdiplusVersion = 1;
result.DebugEventCallback = IntPtr.Zero;
result.SuppressBackgroundThread = 0;
result.SuppressExternalCodecs = 0;
return result;
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct GdiplusStartupOutput
{
internal IntPtr NotificationHook;
internal IntPtr NotificationUnhook;
internal static GdiplusStartupOutput MakeGdiplusStartupOutput()
{
GdiplusStartupOutput result = new GdiplusStartupOutput();
result.NotificationHook = result.NotificationUnhook = IntPtr.Zero;
return result;
}
}
[DllImport("gdiplus.dll")]
public static extern Status GdiplusStartup(ref ulong token, ref GdiplusStartupInput input, ref GdiplusStartupOutput output);
[DllImport("gdiplus.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern Status GdipLoadImageFromStream([MarshalAs(UnmanagedType.Interface, MarshalTypeRef = typeof(IStream))] IStream stream, out IntPtr image);
[DllImport("gdiplus.dll")]
public static extern Status GdipCreateHICONFromBitmap(IntPtr bmp, out IntPtr HandleIcon);
[DllImport("gdiplus.dll")]
internal static extern Status GdipDisposeImage(IntPtr image);
static Gdip()
{
ulong token = 0;
var input = GdiplusStartupInput.MakeGdiplusStartupInput();
var output = GdiplusStartupOutput.MakeGdiplusStartupOutput();
GdiplusStartup(ref token, ref input, ref output);
}
}
}

30
src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
@ -10,10 +12,34 @@ namespace Avalonia.Win32
{
public class IconImpl : IWindowIconImpl
{
public IntPtr HIcon { get; set; }
private readonly MemoryStream _ms;
public IconImpl(Stream data)
{
_ms = new MemoryStream();
data.CopyTo(_ms);
_ms.Seek(0, SeekOrigin.Begin);
IntPtr bitmap;
var status = Gdip.GdipLoadImageFromStream(new ComIStreamWrapper(_ms), out bitmap);
if (status != Gdip.Status.Ok)
throw new Exception("Unable to load icon, gdip status: " + (int) status);
IntPtr icon;
status = Gdip.GdipCreateHICONFromBitmap(bitmap, out icon);
if (status != Gdip.Status.Ok)
throw new Exception("Unable to create HICON, gdip status: " + (int)status);
Gdip.GdipDisposeImage(bitmap);
HIcon = icon;
}
public IntPtr HIcon { get;}
public void Save(Stream outputStream)
{
throw new NotImplementedException();
lock (_ms)
{
_ms.Seek(0, SeekOrigin.Begin);
_ms.CopyTo(outputStream);
}
}
}
}

16
src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs

@ -11,10 +11,20 @@ namespace Avalonia.Win32
partial class Win32Platform
{
//TODO: An actual implementation
public IWindowIconImpl LoadIcon(string fileName) => new IconImpl();
public IWindowIconImpl LoadIcon(string fileName)
{
//No file IO for netstandard, still waiting for proper net core tooling
throw new NotSupportedException();
}
public IWindowIconImpl LoadIcon(Stream stream) => new IconImpl();
public IWindowIconImpl LoadIcon(Stream stream) => new IconImpl(stream);
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) => new IconImpl();
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
var ms = new MemoryStream();
bitmap.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
return new IconImpl(ms);
}
}
}

Loading…
Cancel
Save