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 @@  +