diff --git a/Perspex.Direct2D1.RenderTests/Controls/BorderTests.cs b/Perspex.Direct2D1.RenderTests/Controls/BorderTests.cs
new file mode 100644
index 0000000000..caa36af0a7
--- /dev/null
+++ b/Perspex.Direct2D1.RenderTests/Controls/BorderTests.cs
@@ -0,0 +1,39 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Direct2D1.RenderTests.Controls
+{
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using Perspex.Controls;
+ using Perspex.Media;
+
+ [TestClass]
+ public class BorderTests : TestBase
+ {
+ public BorderTests()
+ : base(@"Controls\Border")
+ {
+ }
+
+ [TestMethod]
+ public void Border_1px_Border()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Content = new Border
+ {
+ BorderBrush = Brushes.Black,
+ BorderThickness = 1,
+ }
+ };
+
+ this.RenderToFile(target);
+ }
+ }
+}
diff --git a/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj b/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
new file mode 100644
index 0000000000..7723fea4b1
--- /dev/null
+++ b/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
@@ -0,0 +1,101 @@
+
+
+
+ Debug
+ AnyCPU
+ {DABFD304-D6A4-4752-8123-C2CCF7AC7831}
+ Library
+ Properties
+ Perspex.Direct2D1.RenderTests
+ Perspex.Direct2D1.RenderTests
+ v4.5
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ ..\packages\Splat.1.1.1\lib\Net45\Splat.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {3e908f67-5543-4879-a1dc-08eace79b3cd}
+ Perspex.Direct2D1
+
+
+ {3c9f40da-d2a5-43a1-a272-e965876c6d46}
+ Perspex
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Perspex.Direct2D1.RenderTests/Properties/AssemblyInfo.cs b/Perspex.Direct2D1.RenderTests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..16d3a8baa4
--- /dev/null
+++ b/Perspex.Direct2D1.RenderTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perspex.Direct2D1.RenderTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Perspex.Direct2D1.RenderTests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("21fcc0e6-150b-43c4-a658-23a354ec33d9")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Perspex.Direct2D1.RenderTests/TestBase.cs b/Perspex.Direct2D1.RenderTests/TestBase.cs
new file mode 100644
index 0000000000..968cb582d1
--- /dev/null
+++ b/Perspex.Direct2D1.RenderTests/TestBase.cs
@@ -0,0 +1,49 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Direct2D1.RenderTests
+{
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using Perspex.Controls;
+ using Perspex.Media;
+
+ public class TestBase
+ {
+ static TestBase()
+ {
+ Direct2D1Platform.Initialize();
+ }
+
+ public TestBase(string outputPath)
+ {
+ string testFiles = Path.GetFullPath(@"..\..\..\TestFiles\Direct2D1");
+ this.OutputPath = Path.Combine(testFiles, outputPath);
+ }
+
+ public string OutputPath
+ {
+ get;
+ private set;
+ }
+
+ protected void RenderToFile(Control target, [CallerMemberName] string testName = "")
+ {
+ string path = Path.Combine(this.OutputPath, testName + ".out.png");
+
+ RenderTargetBitmap bitmap = new RenderTargetBitmap(
+ (int)target.Width,
+ (int)target.Height);
+
+ Size size = new Size(target.Width, target.Height);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ bitmap.Render(target);
+ bitmap.Save(path);
+ }
+ }
+}
diff --git a/Perspex.Direct2D1.RenderTests/packages.config b/Perspex.Direct2D1.RenderTests/packages.config
new file mode 100644
index 0000000000..aece880281
--- /dev/null
+++ b/Perspex.Direct2D1.RenderTests/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Perspex.Direct2D1/Direct2D1Platform.cs b/Perspex.Direct2D1/Direct2D1Platform.cs
index c7c5b5e263..2679a9a1ee 100644
--- a/Perspex.Direct2D1/Direct2D1Platform.cs
+++ b/Perspex.Direct2D1/Direct2D1Platform.cs
@@ -19,14 +19,22 @@ namespace Perspex.Direct2D1
private static SharpDX.DirectWrite.Factory dwFactory = new SharpDX.DirectWrite.Factory();
+ private static SharpDX.WIC.ImagingFactory imagingFactory = new SharpDX.WIC.ImagingFactory();
+
private static TextService textService = new TextService(dwFactory);
public static void Initialize()
{
var locator = Locator.CurrentMutable;
+ locator.Register(() => instance, typeof(IPlatformFactory));
locator.Register(() => d2d1Factory, typeof(SharpDX.Direct2D1.Factory));
locator.Register(() => dwFactory, typeof(SharpDX.DirectWrite.Factory));
- locator.Register(() => instance, typeof(IPlatformFactory));
+ locator.Register(() => imagingFactory, typeof(SharpDX.WIC.ImagingFactory));
+ }
+
+ public IBitmapImpl CreateBitmap(int width, int height)
+ {
+ return new BitmapImpl(imagingFactory, width, height);
}
public IRenderer CreateRenderer(IntPtr handle, double width, double height)
@@ -34,6 +42,11 @@ namespace Perspex.Direct2D1
return new Renderer(handle, width, height);
}
+ public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)
+ {
+ return new RenderTargetBitmapImpl(imagingFactory, d2d1Factory, width, height);
+ }
+
public IStreamGeometryImpl CreateStreamGeometry()
{
return new StreamGeometryImpl();
diff --git a/Perspex.Direct2D1/Media/Imaging/BitmapImpl.cs b/Perspex.Direct2D1/Media/Imaging/BitmapImpl.cs
new file mode 100644
index 0000000000..7426b6446d
--- /dev/null
+++ b/Perspex.Direct2D1/Media/Imaging/BitmapImpl.cs
@@ -0,0 +1,56 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Direct2D1.Media
+{
+ using System;
+ using System.IO;
+ using Perspex.Platform;
+ using SharpDX.WIC;
+
+ public class BitmapImpl : IBitmapImpl
+ {
+ private ImagingFactory factory;
+
+ public BitmapImpl(ImagingFactory factory, int width, int height)
+ {
+ this.factory = factory;
+ this.WicImpl = new Bitmap(
+ factory,
+ width,
+ height,
+ PixelFormat.Format32bppPBGRA,
+ BitmapCreateCacheOption.CacheOnLoad);
+ }
+
+ public Bitmap WicImpl
+ {
+ get;
+ private set;
+ }
+
+ public void Save(string fileName)
+ {
+ if (Path.GetExtension(fileName) != ".png")
+ {
+ // Yeah, we need to support other formats.
+ throw new NotSupportedException("Use PNG, stoopid.");
+ }
+
+ using (FileStream s = new FileStream(fileName, FileMode.Create))
+ {
+ PngBitmapEncoder encoder = new PngBitmapEncoder(factory);
+ encoder.Initialize(s);
+
+ BitmapFrameEncode frame = new BitmapFrameEncode(encoder);
+ frame.Initialize();
+ frame.WriteSource(this.WicImpl);
+ frame.Commit();
+ encoder.Commit();
+ }
+ }
+ }
+}
diff --git a/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs b/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
new file mode 100644
index 0000000000..cc7ef83380
--- /dev/null
+++ b/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
@@ -0,0 +1,41 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Direct2D1.Media
+{
+ using System;
+ using Perspex.Platform;
+ using SharpDX.Direct2D1;
+ using SharpDX.WIC;
+
+ public class RenderTargetBitmapImpl : BitmapImpl, IRenderTargetBitmapImpl
+ {
+ private WicRenderTarget target;
+
+ public RenderTargetBitmapImpl(
+ ImagingFactory imagingFactory,
+ Factory d2dFactory,
+ int width,
+ int height)
+ : base(imagingFactory, width, height)
+ {
+ this.target = new WicRenderTarget(
+ d2dFactory,
+ this.WicImpl,
+ new RenderTargetProperties
+ {
+ DpiX = 96,
+ DpiY = 96,
+ });
+ }
+
+ public void Render(IVisual visual)
+ {
+ Renderer renderer = new Renderer(this.target);
+ renderer.Render(visual);
+ }
+ }
+}
diff --git a/Perspex.Direct2D1/Perspex.Direct2D1.csproj b/Perspex.Direct2D1/Perspex.Direct2D1.csproj
index c1fa678846..0d4b96dded 100644
--- a/Perspex.Direct2D1/Perspex.Direct2D1.csproj
+++ b/Perspex.Direct2D1/Perspex.Direct2D1.csproj
@@ -64,6 +64,8 @@
+
+
diff --git a/Perspex.Direct2D1/Renderer.cs b/Perspex.Direct2D1/Renderer.cs
index 337fb294f6..17dd447b52 100644
--- a/Perspex.Direct2D1/Renderer.cs
+++ b/Perspex.Direct2D1/Renderer.cs
@@ -23,7 +23,7 @@ namespace Perspex.Direct2D1
///
/// The render target.
///
- private WindowRenderTarget renderTarget;
+ private RenderTarget renderTarget;
///
/// Initializes a new instance of the class.
@@ -52,6 +52,17 @@ namespace Perspex.Direct2D1
hwndProperties);
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The render target.
+ public Renderer(RenderTarget renderTarget)
+ {
+ this.Direct2DFactory = Locator.Current.GetService();
+ this.DirectWriteFactory = Locator.Current.GetService();
+ this.renderTarget = renderTarget;
+ }
+
///
/// Gets the Direct2D factory.
///
@@ -89,7 +100,16 @@ namespace Perspex.Direct2D1
/// The new height.
public void Resize(int width, int height)
{
- this.renderTarget.Resize(new Size2(width, height));
+ WindowRenderTarget window = this.renderTarget as WindowRenderTarget;
+
+ if (window == null)
+ {
+ throw new InvalidOperationException(string.Format(
+ "A renderer with a target of type '{0}' cannot be resized.",
+ this.renderTarget.GetType().Name));
+ }
+
+ window.Resize(new Size2(width, height));
}
///
diff --git a/Perspex.sln b/Perspex.sln
index 64cb4832b4..be5c5e7f39 100644
--- a/Perspex.sln
+++ b/Perspex.sln
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.UnitTests", "Perspe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Direct2D1", "Perspex.Direct2D1\Perspex.Direct2D1.csproj", "{3E908F67-5543-4879-A1DC-08EACE79B3CD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Direct2D1.RenderTests", "Perspex.Direct2D1.RenderTests\Perspex.Direct2D1.RenderTests.csproj", "{DABFD304-D6A4-4752-8123-C2CCF7AC7831}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -39,6 +41,10 @@ Global
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Perspex/Media/IDrawingContext.cs b/Perspex/Media/IDrawingContext.cs
index e009f58c59..92a001169a 100644
--- a/Perspex/Media/IDrawingContext.cs
+++ b/Perspex/Media/IDrawingContext.cs
@@ -11,7 +11,7 @@ namespace Perspex.Media
///
/// Defines the interface through which drawing occurs.
///
- public interface IDrawingContext
+ public interface IDrawingContext : IDisposable
{
///
/// Draws a geometry.
diff --git a/Perspex/Media/Imaging/Bitmap.cs b/Perspex/Media/Imaging/Bitmap.cs
new file mode 100644
index 0000000000..5db65f7a0b
--- /dev/null
+++ b/Perspex/Media/Imaging/Bitmap.cs
@@ -0,0 +1,36 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Media
+{
+ using Perspex.Platform;
+ using Splat;
+
+ public class Bitmap
+ {
+ public Bitmap(int width, int height)
+ {
+ IPlatformFactory factory = Locator.Current.GetService();
+ this.PlatformImpl = factory.CreateBitmap(width, height);
+ }
+
+ protected Bitmap(IBitmapImpl impl)
+ {
+ this.PlatformImpl = impl;
+ }
+
+ public IBitmapImpl PlatformImpl
+ {
+ get;
+ private set;
+ }
+
+ public void Save(string fileName)
+ {
+ this.PlatformImpl.Save(fileName);
+ }
+ }
+}
diff --git a/Perspex/Media/Imaging/RenderTargetBitmap.cs b/Perspex/Media/Imaging/RenderTargetBitmap.cs
new file mode 100644
index 0000000000..fe1ccfb26d
--- /dev/null
+++ b/Perspex/Media/Imaging/RenderTargetBitmap.cs
@@ -0,0 +1,35 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Media
+{
+ using Perspex.Platform;
+ using Splat;
+
+ public class RenderTargetBitmap : Bitmap
+ {
+ public RenderTargetBitmap(int width, int height)
+ : base(CreateImpl(width, height))
+ {
+ }
+
+ public new IRenderTargetBitmapImpl PlatformImpl
+ {
+ get { return (IRenderTargetBitmapImpl)base.PlatformImpl; }
+ }
+
+ public void Render(IVisual visual)
+ {
+ this.PlatformImpl.Render(visual);
+ }
+
+ private static IBitmapImpl CreateImpl(int width, int height)
+ {
+ IPlatformFactory factory = Locator.Current.GetService();
+ return factory.CreateRenderTargetBitmap(width, height);
+ }
+ }
+}
diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj
index 65259fd5bd..1a2bc748e3 100644
--- a/Perspex/Perspex.csproj
+++ b/Perspex/Perspex.csproj
@@ -90,6 +90,10 @@
+
+
+
+
diff --git a/Perspex/Platform/IBitmapImpl.cs b/Perspex/Platform/IBitmapImpl.cs
new file mode 100644
index 0000000000..0bbb5314cb
--- /dev/null
+++ b/Perspex/Platform/IBitmapImpl.cs
@@ -0,0 +1,13 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Platform
+{
+ public interface IBitmapImpl
+ {
+ void Save(string fileName);
+ }
+}
diff --git a/Perspex/Platform/IPlatformFactory.cs b/Perspex/Platform/IPlatformFactory.cs
index 26ec83855b..28c934e415 100644
--- a/Perspex/Platform/IPlatformFactory.cs
+++ b/Perspex/Platform/IPlatformFactory.cs
@@ -10,10 +10,14 @@ namespace Perspex.Platform
public interface IPlatformFactory
{
+ IBitmapImpl CreateBitmap(int width, int height);
+
IStreamGeometryImpl CreateStreamGeometry();
IRenderer CreateRenderer(IntPtr handle, double width, double height);
+ IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height);
+
ITextService GetTextService();
}
}
diff --git a/Perspex/Platform/IRenderTargetBitmapImpl.cs b/Perspex/Platform/IRenderTargetBitmapImpl.cs
new file mode 100644
index 0000000000..dc20a78304
--- /dev/null
+++ b/Perspex/Platform/IRenderTargetBitmapImpl.cs
@@ -0,0 +1,13 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Platform
+{
+ public interface IRenderTargetBitmapImpl : IBitmapImpl
+ {
+ void Render(IVisual visual);
+ }
+}
diff --git a/TestFiles/Direct2D1/Controls/Border/Border_1px_Border.out.png b/TestFiles/Direct2D1/Controls/Border/Border_1px_Border.out.png
new file mode 100644
index 0000000000..ac360079e7
Binary files /dev/null and b/TestFiles/Direct2D1/Controls/Border/Border_1px_Border.out.png differ
diff --git a/packages/repositories.config b/packages/repositories.config
index 4385439ce2..10921361a8 100644
--- a/packages/repositories.config
+++ b/packages/repositories.config
@@ -1,5 +1,6 @@
+