Browse Source

Implemented RenderTargetBitmap

And added a test that outputs an image using it (doesn't actually
compare the image yet)
pull/4/head
Steven Kirk 12 years ago
parent
commit
cea271de90
  1. 39
      Perspex.Direct2D1.RenderTests/Controls/BorderTests.cs
  2. 101
      Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
  3. 36
      Perspex.Direct2D1.RenderTests/Properties/AssemblyInfo.cs
  4. 49
      Perspex.Direct2D1.RenderTests/TestBase.cs
  5. 4
      Perspex.Direct2D1.RenderTests/packages.config
  6. 15
      Perspex.Direct2D1/Direct2D1Platform.cs
  7. 56
      Perspex.Direct2D1/Media/Imaging/BitmapImpl.cs
  8. 41
      Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
  9. 2
      Perspex.Direct2D1/Perspex.Direct2D1.csproj
  10. 24
      Perspex.Direct2D1/Renderer.cs
  11. 6
      Perspex.sln
  12. 2
      Perspex/Media/IDrawingContext.cs
  13. 36
      Perspex/Media/Imaging/Bitmap.cs
  14. 35
      Perspex/Media/Imaging/RenderTargetBitmap.cs
  15. 4
      Perspex/Perspex.csproj
  16. 13
      Perspex/Platform/IBitmapImpl.cs
  17. 4
      Perspex/Platform/IPlatformFactory.cs
  18. 13
      Perspex/Platform/IRenderTargetBitmapImpl.cs
  19. BIN
      TestFiles/Direct2D1/Controls/Border/Border_1px_Border.out.png
  20. 1
      packages/repositories.config

39
Perspex.Direct2D1.RenderTests/Controls/BorderTests.cs

@ -0,0 +1,39 @@
// -----------------------------------------------------------------------
// <copyright file="BorderTests.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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);
}
}
}

101
Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DABFD304-D6A4-4752-8123-C2CCF7AC7831}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Perspex.Direct2D1.RenderTests</RootNamespace>
<AssemblyName>Perspex.Direct2D1.RenderTests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Splat, Version=1.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Splat.1.1.1\lib\Net45\Splat.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="Controls\BorderTests.cs" />
<Compile Include="TestBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Perspex.Direct2D1\Perspex.Direct2D1.csproj">
<Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
<Name>Perspex.Direct2D1</Name>
</ProjectReference>
<ProjectReference Include="..\Perspex\Perspex.csproj">
<Project>{3c9f40da-d2a5-43a1-a272-e965876c6d46}</Project>
<Name>Perspex</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

36
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")]

49
Perspex.Direct2D1.RenderTests/TestBase.cs

@ -0,0 +1,49 @@
// -----------------------------------------------------------------------
// <copyright file="TestBase.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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);
}
}
}

4
Perspex.Direct2D1.RenderTests/packages.config

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Splat" version="1.1.1" targetFramework="net45" />
</packages>

15
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();

56
Perspex.Direct2D1/Media/Imaging/BitmapImpl.cs

@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="BitmapImpl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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();
}
}
}
}

41
Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs

@ -0,0 +1,41 @@
// -----------------------------------------------------------------------
// <copyright file="RenderTargetBitmapImpl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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);
}
}
}

2
Perspex.Direct2D1/Perspex.Direct2D1.csproj

@ -64,6 +64,8 @@
<ItemGroup>
<Compile Include="Direct2D1Platform.cs" />
<Compile Include="Media\DrawingContext.cs" />
<Compile Include="Media\Imaging\RenderTargetBitmapImpl.cs" />
<Compile Include="Media\Imaging\BitmapImpl.cs" />
<Compile Include="Media\StreamGeometryContextImpl.cs" />
<Compile Include="Media\GeometryImpl.cs" />
<Compile Include="Media\StreamGeometryImpl.cs" />

24
Perspex.Direct2D1/Renderer.cs

@ -23,7 +23,7 @@ namespace Perspex.Direct2D1
/// <summary>
/// The render target.
/// </summary>
private WindowRenderTarget renderTarget;
private RenderTarget renderTarget;
/// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class.
@ -52,6 +52,17 @@ namespace Perspex.Direct2D1
hwndProperties);
}
/// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class.
/// </summary>
/// <param name="renderTarget">The render target.</param>
public Renderer(RenderTarget renderTarget)
{
this.Direct2DFactory = Locator.Current.GetService<Factory>();
this.DirectWriteFactory = Locator.Current.GetService<DwFactory>();
this.renderTarget = renderTarget;
}
/// <summary>
/// Gets the Direct2D factory.
/// </summary>
@ -89,7 +100,16 @@ namespace Perspex.Direct2D1
/// <param name="height">The new height.</param>
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));
}
/// <summary>

6
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

2
Perspex/Media/IDrawingContext.cs

@ -11,7 +11,7 @@ namespace Perspex.Media
/// <summary>
/// Defines the interface through which drawing occurs.
/// </summary>
public interface IDrawingContext
public interface IDrawingContext : IDisposable
{
/// <summary>
/// Draws a geometry.

36
Perspex/Media/Imaging/Bitmap.cs

@ -0,0 +1,36 @@
// -----------------------------------------------------------------------
// <copyright file="Bitmap.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Media
{
using Perspex.Platform;
using Splat;
public class Bitmap
{
public Bitmap(int width, int height)
{
IPlatformFactory factory = Locator.Current.GetService<IPlatformFactory>();
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);
}
}
}

35
Perspex/Media/Imaging/RenderTargetBitmap.cs

@ -0,0 +1,35 @@
// -----------------------------------------------------------------------
// <copyright file="RenderTargetBitmap.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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<IPlatformFactory>();
return factory.CreateRenderTargetBitmap(width, height);
}
}
}

4
Perspex/Perspex.csproj

@ -90,6 +90,10 @@
<Compile Include="Input\Raw\RawInputEventArgs.cs" />
<Compile Include="Input\Raw\RawMouseEventArgs.cs" />
<Compile Include="Media\Brushes.cs" />
<Compile Include="Media\Imaging\Bitmap.cs" />
<Compile Include="Media\Imaging\RenderTargetBitmap.cs" />
<Compile Include="Platform\IRenderTargetBitmapImpl.cs" />
<Compile Include="Platform\IBitmapImpl.cs" />
<Compile Include="Platform\IPlatformFactory.cs" />
<Compile Include="Platform\IStreamGeometryContextImpl.cs" />
<Compile Include="Platform\IGeometryImpl.cs" />

13
Perspex/Platform/IBitmapImpl.cs

@ -0,0 +1,13 @@
// -----------------------------------------------------------------------
// <copyright file="IBitmapImpl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Platform
{
public interface IBitmapImpl
{
void Save(string fileName);
}
}

4
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();
}
}

13
Perspex/Platform/IRenderTargetBitmapImpl.cs

@ -0,0 +1,13 @@
// -----------------------------------------------------------------------
// <copyright file="IRenderTargetBitmapImpl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Platform
{
public interface IRenderTargetBitmapImpl : IBitmapImpl
{
void Render(IVisual visual);
}
}

BIN
TestFiles/Direct2D1/Controls/Border/Border_1px_Border.out.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

1
packages/repositories.config

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\Perspex.Direct2D1.RenderTests\packages.config" />
<repository path="..\Perspex.Direct2D1\packages.config" />
<repository path="..\Perspex.UnitTests\packages.config" />
<repository path="..\Perspex.Windows\packages.config" />

Loading…
Cancel
Save