зеркало из https://github.com/microsoft/Win2D.git
Add CanvasComposition, for interop with Windows.UI.Composition
This commit is contained in:
Родитель
f9e4af8b74
Коммит
f1f6c40b40
|
@ -152,6 +152,7 @@
|
|||
</UAPProject>
|
||||
<UAPProject Include="samples\SimpleSample\UAP\SimpleSample.uap.csproj" />
|
||||
<UAPProject Include="samples\CoreWindowExample\UAP\CoreWindowExample.uap.csproj" />
|
||||
<UAPProject Include="samples\CompositionExample\CompositionExample.csproj" />
|
||||
<UAPProject Include="samples\ExampleGallery\Direct3DInterop\UAP\ExampleGallery.Direct3DInterop.uap.vcxproj">
|
||||
<BuildInParallel>false</BuildInParallel>
|
||||
</UAPProject>
|
||||
|
|
|
@ -105,6 +105,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleGallery.Direct3DInte
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleGallery.Direct3DInterop.Shared", "samples\ExampleGallery\Direct3DInterop\Shared\ExampleGallery.Direct3DInterop.Shared.vcxitems", "{8E486BCA-FE9B-4F99-9D2E-A277905E84EB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompositionExample", "Samples\CompositionExample\CompositionExample.csproj", "{60836F00-A727-402B-AFD7-2779675B29A2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
winrt\test.managed\Shared\winrt.test.managed.Shared.projitems*{70fb7b71-d56c-4bf1-9282-27aa58043cc0}*SharedItemsImports = 4
|
||||
|
@ -321,6 +323,24 @@ Global
|
|||
{A81F96D0-4924-40E3-A463-3CB9EE55AA93}.Release|Win32.Build.0 = Release|Win32
|
||||
{A81F96D0-4924-40E3-A463-3CB9EE55AA93}.Release|x64.ActiveCfg = Release|x64
|
||||
{A81F96D0-4924-40E3-A463-3CB9EE55AA93}.Release|x64.Build.0 = Release|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|Win32.Deploy.0 = Debug|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|x64.Build.0 = Debug|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|ARM.Build.0 = Release|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|Win32.Build.0 = Release|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|Win32.Deploy.0 = Release|Win32
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|x64.ActiveCfg = Release|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|x64.Build.0 = Release|x64
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2}.Release|x64.Deploy.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -361,5 +381,6 @@ Global
|
|||
{81A681BB-9434-420E-8A27-1656AEFDCA4B} = {671EACB0-6255-4050-B092-1A874625AD5C}
|
||||
{A81F96D0-4924-40E3-A463-3CB9EE55AA93} = {81A681BB-9434-420E-8A27-1656AEFDCA4B}
|
||||
{8E486BCA-FE9B-4F99-9D2E-A277905E84EB} = {81A681BB-9434-420E-8A27-1656AEFDCA4B}
|
||||
{60836F00-A727-402B-AFD7-2779675B29A2} = {EC7BD4FF-9DAE-4698-9FDA-244478B0203B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.UI.Composition;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Composition;
|
||||
using Windows.UI.Core;
|
||||
|
||||
namespace CompositionExample
|
||||
{
|
||||
class App : IFrameworkView
|
||||
{
|
||||
CoreWindow window;
|
||||
Compositor compositor;
|
||||
CanvasDevice device;
|
||||
CompositionGraphicsDevice compositionGraphicsDevice;
|
||||
|
||||
DrawingSurfaceRenderer drawingSurfaceRenderer;
|
||||
SwapChainRenderer swapChainRenderer;
|
||||
|
||||
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
||||
Random rnd = new Random();
|
||||
|
||||
public void Initialize(CoreApplicationView applicationView)
|
||||
{
|
||||
applicationView.Activated += applicationView_Activated;
|
||||
}
|
||||
|
||||
public void Uninitialize()
|
||||
{
|
||||
swapChainRenderer?.Dispose();
|
||||
cancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
void applicationView_Activated(CoreApplicationView sender, IActivatedEventArgs args)
|
||||
{
|
||||
CoreWindow.GetForCurrentThread().Activate();
|
||||
}
|
||||
|
||||
public void Load(string entryPoint)
|
||||
{
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
CoreWindow.GetForCurrentThread().Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessUntilQuit);
|
||||
}
|
||||
|
||||
public void SetWindow(CoreWindow window)
|
||||
{
|
||||
this.window = window;
|
||||
|
||||
CoreApplication.Suspending += CoreApplication_Suspending;
|
||||
|
||||
compositor = new Compositor();
|
||||
|
||||
CreateDevice();
|
||||
|
||||
drawingSurfaceRenderer = new DrawingSurfaceRenderer(compositor, compositionGraphicsDevice);
|
||||
|
||||
swapChainRenderer = new SwapChainRenderer(compositor);
|
||||
swapChainRenderer.SetDevice(device, new Size(window.Bounds.Width, window.Bounds.Height));
|
||||
|
||||
drawingSurfaceRenderer.Visual.Offset = new Vector3(-drawingSurfaceRenderer.Size.ToVector2(), 0);
|
||||
swapChainRenderer.Visual.Offset = new Vector3((float)window.Bounds.Width, (float)window.Bounds.Height, 0);
|
||||
|
||||
var rootVisual = compositor.CreateContainerVisual();
|
||||
rootVisual.Children.InsertAtTop(swapChainRenderer.Visual);
|
||||
rootVisual.Children.InsertAtTop(drawingSurfaceRenderer.Visual);
|
||||
|
||||
compositor.CreateTargetForCurrentView().Root = rootVisual;
|
||||
|
||||
var ignoredTask = UpdateVisualsLoop();
|
||||
}
|
||||
|
||||
async Task UpdateVisualsLoop()
|
||||
{
|
||||
var token = cancellationTokenSource.Token;
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
UpdateVisual(swapChainRenderer.Visual, swapChainRenderer.Size);
|
||||
UpdateVisual(drawingSurfaceRenderer.Visual, drawingSurfaceRenderer.Size);
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateVisual(Visual visual, Size size)
|
||||
{
|
||||
UpdateVisualPosition(visual, size);
|
||||
UpdateVisualOpacity(visual);
|
||||
}
|
||||
|
||||
void UpdateVisualPosition(Visual visual, Size size)
|
||||
{
|
||||
var oldOffset = visual.Offset;
|
||||
var newOffset = new Vector3(
|
||||
(float)(rnd.NextDouble() * (window.Bounds.Width - size.Width)),
|
||||
(float)(rnd.NextDouble() * (window.Bounds.Height - size.Height)),
|
||||
0);
|
||||
|
||||
visual.Offset = newOffset;
|
||||
visual.Size = size.ToVector2();
|
||||
|
||||
AnimateOffset(visual, oldOffset, newOffset);
|
||||
}
|
||||
|
||||
void UpdateVisualOpacity(Visual visual)
|
||||
{
|
||||
var oldOpacity = visual.Opacity;
|
||||
var newOpacity = (float)rnd.NextDouble();
|
||||
|
||||
var animation = compositor.CreateScalarKeyFrameAnimation();
|
||||
animation.InsertKeyFrame(0, oldOpacity);
|
||||
animation.InsertKeyFrame(1, newOpacity);
|
||||
|
||||
visual.Opacity = newOpacity;
|
||||
visual.StartAnimation("Opacity", animation);
|
||||
}
|
||||
|
||||
void AnimateOffset(Visual visual, Vector3 oldOffset, Vector3 newOffset)
|
||||
{
|
||||
var animation = compositor.CreateVector3KeyFrameAnimation();
|
||||
animation.InsertKeyFrame(0, oldOffset);
|
||||
animation.InsertKeyFrame(1, newOffset);
|
||||
animation.Duration = TimeSpan.FromSeconds(1);
|
||||
|
||||
visual.StartAnimation("Offset", animation);
|
||||
}
|
||||
|
||||
void CoreApplication_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
device.Trim();
|
||||
}
|
||||
catch (Exception e) when (device.IsDeviceLost(e.HResult))
|
||||
{
|
||||
device.RaiseDeviceLost();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDevice()
|
||||
{
|
||||
device = CanvasDevice.GetSharedDevice();
|
||||
device.DeviceLost += Device_DeviceLost;
|
||||
|
||||
if (compositionGraphicsDevice == null)
|
||||
{
|
||||
compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, device);
|
||||
}
|
||||
else
|
||||
{
|
||||
CanvasComposition.SetCanvasDevice(compositionGraphicsDevice, device);
|
||||
}
|
||||
|
||||
if (swapChainRenderer != null)
|
||||
swapChainRenderer.SetDevice(device, new Size(window.Bounds.Width, window.Bounds.Height));
|
||||
}
|
||||
|
||||
void Device_DeviceLost(CanvasDevice sender, object args)
|
||||
{
|
||||
device.DeviceLost -= Device_DeviceLost;
|
||||
var unwaitedTask = window.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => CreateDevice());
|
||||
}
|
||||
}
|
||||
|
||||
class ViewSource : IFrameworkViewSource
|
||||
{
|
||||
public IFrameworkView CreateView()
|
||||
{
|
||||
return new App();
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
CoreApplication.Run(new ViewSource());
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.1 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.1 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 12 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.7 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.2 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 5.6 KiB |
|
@ -0,0 +1,125 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">Win32</Platform>
|
||||
<ProjectGuid>{60836F00-A727-402B-AFD7-2779675B29A2}</ProjectGuid>
|
||||
<OutputType>AppContainerExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CompositionExample</RootNamespace>
|
||||
<AssemblyName>CompositionExample</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\build\Win2D.cs.props" />
|
||||
<PropertyGroup>
|
||||
<PackageCertificateKeyFile>$(AssetDir)TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\winrt\dll\winrt.dll.uap.vcxproj">
|
||||
<Project>{8cf21e5d-e0a2-4fe7-8e2b-a025cf52dcfb}</Project>
|
||||
<Name>winrt.dll.uap</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.cs" />
|
||||
<Compile Include="DrawingSurfaceRenderer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SwapChainRenderer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
<None Include="$(AssetDir)TemporaryKey.pfx" />
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="$(AssetDir)RuntimeDirectives.rd.xml" />
|
||||
<Content Include="Assets\Logo.scale-100.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-100.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-100.png" />
|
||||
<Content Include="Assets\Square71x71Logo.scale-100.png" />
|
||||
<Content Include="Assets\StoreLogo.scale-100.png" />
|
||||
<Content Include="Assets\WideLogo.scale-100.png" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.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>
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Composition;
|
||||
using System.Numerics;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics.DirectX;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Composition;
|
||||
|
||||
namespace CompositionExample
|
||||
{
|
||||
class DrawingSurfaceRenderer
|
||||
{
|
||||
SpriteVisual drawingSurfaceVisual;
|
||||
CompositionDrawingSurface drawingSurface;
|
||||
|
||||
public Visual Visual { get { return drawingSurfaceVisual; } }
|
||||
|
||||
public Size Size { get { return drawingSurface.Size; } }
|
||||
|
||||
public DrawingSurfaceRenderer(Compositor compositor, CompositionGraphicsDevice compositionGraphicsDevice)
|
||||
{
|
||||
drawingSurfaceVisual = compositor.CreateSpriteVisual();
|
||||
drawingSurface = compositionGraphicsDevice.CreateDrawingSurface(new Size(256, 256), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
|
||||
drawingSurfaceVisual.Brush = compositor.CreateSurfaceBrush(drawingSurface);
|
||||
DrawDrawingSurface();
|
||||
|
||||
compositionGraphicsDevice.RenderingDeviceReplaced += CompositionGraphicsDevice_RenderingDeviceReplaced;
|
||||
}
|
||||
|
||||
void CompositionGraphicsDevice_RenderingDeviceReplaced(CompositionGraphicsDevice sender, RenderingDeviceReplacedEventArgs args)
|
||||
{
|
||||
DrawDrawingSurface();
|
||||
}
|
||||
|
||||
void DrawDrawingSurface()
|
||||
{
|
||||
using (var ds = CanvasComposition.CreateDrawingSession(drawingSurface))
|
||||
{
|
||||
ds.Clear(Colors.Transparent);
|
||||
|
||||
var rect = new Rect(new Point(2, 2), (drawingSurface.Size.ToVector2() - new Vector2(4, 4)).ToSize());
|
||||
|
||||
ds.FillRoundedRectangle(rect, 15, 15, Colors.LightBlue);
|
||||
ds.DrawRoundedRectangle(rect, 15, 15, Colors.Gray, 2);
|
||||
ds.DrawText("This is a composition drawing surface", rect, Colors.Black, new CanvasTextFormat()
|
||||
{
|
||||
FontFamily = "Comic Sans MS",
|
||||
FontSize = 32,
|
||||
WordWrapping = CanvasWordWrapping.WholeWord,
|
||||
VerticalAlignment = CanvasVerticalAlignment.Center,
|
||||
HorizontalAlignment = CanvasHorizontalAlignment.Center
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="Win2DCompositionExample" Publisher="CN=Microsoft Corportation" Version="1.0.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="b6cfff57-2afa-4919-b308-d3c49d4f7a76" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Win2D Composition Example</DisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="CompositionExample.App">
|
||||
<uap:VisualElements DisplayName="Win2D Composition Example" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="CompositionExample" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\WideLogo.png" Square71x71Logo="Assets\Square71x71Logo.png">
|
||||
<uap:ShowNameOnTiles>
|
||||
<uap:ShowOn Tile="square150x150Logo" />
|
||||
<uap:ShowOn Tile="wide310x150Logo" />
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
</Capabilities>
|
||||
</Package>
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("CompositionExample")]
|
||||
[assembly: AssemblyProduct("Win2D")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Graphics.Canvas;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Composition;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Composition;
|
||||
|
||||
namespace CompositionExample
|
||||
{
|
||||
class SwapChainRenderer : IDisposable
|
||||
{
|
||||
Compositor compositor;
|
||||
CanvasSwapChain swapChain;
|
||||
SpriteVisual swapChainVisual;
|
||||
CancellationTokenSource swapChainDrawLoopCancellationTokenSource;
|
||||
int drawCount;
|
||||
|
||||
public Visual Visual { get { return swapChainVisual; } }
|
||||
|
||||
public Size Size
|
||||
{
|
||||
get
|
||||
{
|
||||
if (swapChain == null)
|
||||
return new Size(0, 0);
|
||||
|
||||
return swapChain.Size;
|
||||
}
|
||||
}
|
||||
|
||||
public SwapChainRenderer(Compositor compositor)
|
||||
{
|
||||
this.compositor = compositor;
|
||||
swapChainVisual = compositor.CreateSpriteVisual();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
swapChainDrawLoopCancellationTokenSource?.Cancel();
|
||||
swapChain?.Dispose();
|
||||
}
|
||||
|
||||
public void SetDevice(CanvasDevice device, Size windowSize)
|
||||
{
|
||||
swapChainDrawLoopCancellationTokenSource?.Cancel();
|
||||
|
||||
swapChain = new CanvasSwapChain(device, 256, 256, 96);
|
||||
swapChainVisual.Brush = compositor.CreateSurfaceBrush(CanvasComposition.CreateCompositionSurfaceForSwapChain(compositor, swapChain));
|
||||
|
||||
swapChainDrawLoopCancellationTokenSource = new CancellationTokenSource();
|
||||
Task.Factory.StartNew(
|
||||
DrawLoop,
|
||||
swapChainDrawLoopCancellationTokenSource.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
void DrawLoop()
|
||||
{
|
||||
var canceled = swapChainDrawLoopCancellationTokenSource.Token;
|
||||
|
||||
try
|
||||
{
|
||||
while (!canceled.IsCancellationRequested)
|
||||
{
|
||||
DrawSwapChain(swapChain);
|
||||
}
|
||||
|
||||
swapChain.Dispose();
|
||||
}
|
||||
catch (Exception e) when (swapChain.Device.IsDeviceLost(e.HResult))
|
||||
{
|
||||
swapChain.Device.RaiseDeviceLost();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSwapChain(CanvasSwapChain swapChain)
|
||||
{
|
||||
++drawCount;
|
||||
|
||||
using (var ds = swapChain.CreateDrawingSession(Colors.Transparent))
|
||||
{
|
||||
var size = swapChain.Size.ToVector2();
|
||||
var radius = (Math.Min(size.X, size.Y) / 2.0f) - 4.0f;
|
||||
|
||||
var center = size / 2;
|
||||
|
||||
ds.FillCircle(center, radius, Colors.LightGoldenrodYellow);
|
||||
ds.DrawCircle(center, radius, Colors.LightGray);
|
||||
|
||||
double mu = (-drawCount / 50.0f);
|
||||
|
||||
for (int i =0; i < 16; ++i)
|
||||
{
|
||||
double a = mu + (i / 16.0) * Math.PI * 2;
|
||||
var x = (float)Math.Sin(a);
|
||||
var y = (float)Math.Cos(a);
|
||||
ds.DrawLine(center, center + new Vector2(x, y) * radius, Colors.Black, 5);
|
||||
}
|
||||
|
||||
var rectLength = Math.Sqrt(radius * radius * 2);
|
||||
|
||||
ds.FillCircle(center, (float)rectLength / 2, Colors.LightGoldenrodYellow);
|
||||
|
||||
var rect = new Rect(center.X - rectLength / 2, center.Y - rectLength / 2, rectLength, rectLength);
|
||||
|
||||
ds.DrawText("This is a swap chain",
|
||||
rect,
|
||||
Colors.Black,
|
||||
new CanvasTextFormat()
|
||||
{
|
||||
FontFamily = "Comic Sans MS",
|
||||
FontSize = 24,
|
||||
VerticalAlignment = CanvasVerticalAlignment.Center,
|
||||
HorizontalAlignment = CanvasHorizontalAlignment.Center,
|
||||
WordWrapping = CanvasWordWrapping.WholeWord,
|
||||
});
|
||||
}
|
||||
|
||||
swapChain.Present();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"uap10.0": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-arm-aot": {},
|
||||
"win10-x86": {},
|
||||
"win10-x86-aot": {},
|
||||
"win10-x64": {},
|
||||
"win10-x64-aot": {}
|
||||
}
|
||||
}
|
|
@ -39,9 +39,10 @@ namespace ExampleGallery
|
|||
|
||||
static AppInfo[] apps =
|
||||
{
|
||||
new AppInfo("ExampleGallery", DrawExampleGalleryIcon, Color.FromArgb(255, 0xE7, 0x59, 0x34)) { AddShadow = true },
|
||||
new AppInfo("CoreWindowExample", DrawCoreWindowIcon, Colors.CornflowerBlue) { ImageScale = 0.6f },
|
||||
new AppInfo("SimpleSample", DrawSimpleSampleIcon, Colors.CornflowerBlue) { ImageScale = 0.6f },
|
||||
new AppInfo("ExampleGallery", DrawExampleGalleryIcon, Color.FromArgb(255, 0xE7, 0x59, 0x34)) { AddShadow = true },
|
||||
new AppInfo("CoreWindowExample", DrawCoreWindowIcon, Colors.CornflowerBlue) { ImageScale = 0.6f },
|
||||
new AppInfo("SimpleSample", DrawSimpleSampleIcon, Colors.CornflowerBlue) { ImageScale = 0.6f },
|
||||
new AppInfo("CompositionExample", DrawCompositionExampleIcon, Colors.Goldenrod) { AddShadow = true, ImageScale = 0.6f },
|
||||
};
|
||||
|
||||
|
||||
|
@ -255,11 +256,18 @@ namespace ExampleGallery
|
|||
}
|
||||
|
||||
|
||||
// For CoreWindowExample, we draw the same simple graphics as the sample itself.
|
||||
// For SimpleSample, we draw the same simple graphics as the sample itself.
|
||||
static void DrawSimpleSampleIcon(CanvasDrawingSession ds, IconInfo iconInfo)
|
||||
{
|
||||
ds.DrawEllipse(155, 115, 80, 30, Colors.Black, 3);
|
||||
ds.DrawText("Hello, world!", 100, 100, Colors.Yellow);
|
||||
}
|
||||
|
||||
|
||||
// Generate an icon for CompositionExample
|
||||
private static void DrawCompositionExampleIcon(CanvasDrawingSession ds, IconInfo iconInfo)
|
||||
{
|
||||
ds.DrawText("C", 0, 0, Colors.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace DocPreprocess
|
|||
{
|
||||
new Tag("Experimental", "This API is marked as [Experimental], meaning it may be subject to change in future Win2D releases.") { PropagateTypeTagsToMembers = true },
|
||||
new Tag("Win10", "This API is available on Windows 10 (Universal Windows Platform) only. It is not supported on Windows 8.1 or Phone 8.1."),
|
||||
new Tag("TH2", "This API is available on TH2 only.") { PropagateTypeTagsToMembers = true }, // TODO 5874: update with appropriate text
|
||||
new Tag("NoComposition", "Supported by Win2D but not Windows.UI.Composition."),
|
||||
};
|
||||
|
||||
|
|
|
@ -39,5 +39,27 @@ Licensed under the MIT License. See LICENSE.txt in the project root for license
|
|||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="N:Windows.UI.Composition">
|
||||
<summary>
|
||||
<a href="http://msdn.microsoft.com/library/windows/apps/Windows.UI.Composition">This namespace is documented on MSDN.</a>
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="T:Windows.UI.Composition.Compositor">
|
||||
<tocexclude />
|
||||
</member>
|
||||
|
||||
<member name="T:Windows.UI.Composition.CompositionDrawingSurface">
|
||||
<tocexclude />
|
||||
</member>
|
||||
|
||||
<member name="T:Windows.UI.Composition.CompositionGraphicsDevice">
|
||||
<tocexclude />
|
||||
</member>
|
||||
|
||||
<member name="T:Windows.UI.Composition.ICompositionSurface">
|
||||
<tocexclude />
|
||||
</member>
|
||||
|
||||
</members>
|
||||
</doc>
|
||||
|
|
|
@ -9,9 +9,10 @@ Licensed under the MIT License. See LICENSE.txt in the project root for license
|
|||
|
||||
<File Source="LICENSE.txt" />
|
||||
|
||||
<Sample Source="samples\CoreWindowExample" Destination="CoreWindowExample" />
|
||||
<Sample Source="samples\ExampleGallery" Destination="ExampleGallery" />
|
||||
<Sample Source="samples\SimpleSample" Destination="SimpleSample" />
|
||||
<Sample Source="samples\CoreWindowExample" Destination="CoreWindowExample" />
|
||||
<Sample Source="samples\ExampleGallery" Destination="ExampleGallery" />
|
||||
<Sample Source="samples\SimpleSample" Destination="SimpleSample" />
|
||||
<Sample Source="samples\CompositionExample" Destination="CompositionExample\UAP" />
|
||||
|
||||
<Property Name="AssetDir" Value="build\assets\" />
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace exportsample
|
|||
{
|
||||
// Delete all the directories under the sample (leaving any files in the root). This is to allow
|
||||
// us to catch (re)moved files.
|
||||
if (!Directory.Exists(sample.Destination))
|
||||
return;
|
||||
|
||||
foreach (var dir in Directory.EnumerateDirectories(sample.Destination))
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
-->
|
||||
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Graphics.Canvas</name>
|
||||
</assembly>
|
||||
<members>
|
||||
|
||||
<member name="T:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition" Experimental="true" TH2="true">
|
||||
<summary>
|
||||
Methods for using Win2D with Windows.UI.Composition.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.CreateCompositionGraphicsDevice(Windows.UI.Composition.Compositor,Microsoft.Graphics.Canvas.CanvasDevice)">
|
||||
<summary>
|
||||
Creates a CompositionGraphicsDevice associated with a CanvasDevice.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.CreateCompositionSurfaceForSwapChain(Windows.UI.Composition.Compositor,Microsoft.Graphics.Canvas.CanvasSwapChain)">
|
||||
<summary>
|
||||
Creates an ICompositionSurface associated with a CanvasSwapChain.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.CreateDrawingSession(Windows.UI.Composition.CompositionDrawingSurface)">
|
||||
<summary>
|
||||
Creates a CanvasDrawingSession for drawing to the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
<remarks>
|
||||
<p>
|
||||
The initial content of the drawing surface is undefined, so apps
|
||||
should ensure that they either call Clear or draw over the entire
|
||||
surface.
|
||||
</p>
|
||||
</remarks>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.CreateDrawingSession(Windows.UI.Composition.CompositionDrawingSurface,Windows.Foundation.Rect)">
|
||||
<summary>
|
||||
Creates a CanvasDrawingSession for updating a region of the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.GetCanvasDevice(Windows.UI.Composition.CompositionGraphicsDevice)">
|
||||
<summary>
|
||||
Gets the CanvasDevice associated with the given CompositionGraphicsDevice.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.Resize(Windows.UI.Composition.CompositionDrawingSurface,Windows.Foundation.Size)">
|
||||
<summary>
|
||||
Resizes the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.ResumeDrawing(Windows.UI.Composition.CompositionDrawingSurface)">
|
||||
<summary>
|
||||
Resumes drawing on the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.Scroll(Windows.UI.Composition.CompositionDrawingSurface,System.Nullable{Windows.Foundation.Rect},System.Nullable{Windows.Foundation.Rect},Microsoft.Graphics.Canvas.UI.Composition.Point)">
|
||||
<summary>
|
||||
Scrolls the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.SetCanvasDevice(Windows.UI.Composition.CompositionGraphicsDevice,Microsoft.Graphics.Canvas.CanvasDevice)">
|
||||
<summary>
|
||||
Sets the CanvasDevice associated with the given CompositionGraphicsDevice.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
<member name="M:Microsoft.Graphics.Canvas.UI.Composition.CanvasComposition.SuspendDrawing(Windows.UI.Composition.CompositionDrawingSurface)">
|
||||
<summary>
|
||||
Suspends drawing on the given CompositionDrawingSurface.
|
||||
</summary>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
</doc>
|
|
@ -31,6 +31,10 @@ Licensed under the MIT License. See LICENSE.txt in the project root for license
|
|||
<summary>This namespace defines common types for using Win2D with UI frameworks.</summary>
|
||||
</member>
|
||||
|
||||
<member name="N:Microsoft.Graphics.Canvas.UI.Composition">
|
||||
<summary>This namespace provides Win2D interoperability with Windows.UI.Composition.</summary>
|
||||
</member>
|
||||
|
||||
<member name="N:Microsoft.Graphics.Canvas.UI.Xaml">
|
||||
<summary>This namespace provides Win2D-enabled XAML controls.</summary>
|
||||
</member>
|
||||
|
|
|
@ -13,6 +13,14 @@ namespace Windows.Graphics.Imaging
|
|||
public class SoftwareBitmap { internal SoftwareBitmap() { } }
|
||||
}
|
||||
|
||||
namespace Windows.UI.Composition
|
||||
{
|
||||
public class Compositor { internal Compositor() { } }
|
||||
public class CompositionDrawingSurface { internal CompositionDrawingSurface() { } }
|
||||
public class CompositionGraphicsDevice { internal CompositionGraphicsDevice() { } }
|
||||
public interface ICompositionSurface { }
|
||||
}
|
||||
|
||||
namespace Windows.UI.Input.Inking
|
||||
{
|
||||
public class InkStroke { internal InkStroke() { } }
|
||||
|
@ -200,4 +208,38 @@ namespace Microsoft.Graphics.Canvas.Text
|
|||
set { throw new System.NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Microsoft.Graphics.Canvas.UI.Composition
|
||||
{
|
||||
/// <summary></summary>
|
||||
public static class CanvasComposition
|
||||
{
|
||||
/// <summary></summary>
|
||||
public static Windows.UI.Composition.CompositionGraphicsDevice CreateCompositionGraphicsDevice(Windows.UI.Composition.Compositor compositor, Microsoft.Graphics.Canvas.CanvasDevice canvasDevice) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static Windows.UI.Composition.ICompositionSurface CreateCompositionSurfaceForSwapChain(Windows.UI.Composition.Compositor compositor, Microsoft.Graphics.Canvas.CanvasSwapChain swapChain) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static Microsoft.Graphics.Canvas.CanvasDrawingSession CreateDrawingSession(Windows.UI.Composition.CompositionDrawingSurface drawingSurface) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static Microsoft.Graphics.Canvas.CanvasDrawingSession CreateDrawingSession(Windows.UI.Composition.CompositionDrawingSurface drawingSurface, global::Windows.Foundation.Rect updateRect) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static Microsoft.Graphics.Canvas.CanvasDevice GetCanvasDevice(Windows.UI.Composition.CompositionGraphicsDevice graphicsDevice) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static void Resize(Windows.UI.Composition.CompositionDrawingSurface drawingSurface, global::Windows.Foundation.Size sizeInPixels) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static void ResumeDrawing(Windows.UI.Composition.CompositionDrawingSurface drawingSurface) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static void Scroll(Windows.UI.Composition.CompositionDrawingSurface drawingSurface, global::Windows.Foundation.Rect? scrollRect, global::Windows.Foundation.Rect? clipRect, Point offset) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static void SetCanvasDevice(Windows.UI.Composition.CompositionGraphicsDevice graphicsDevice, Microsoft.Graphics.Canvas.CanvasDevice canvasDevice) { throw new System.NotImplementedException(); }
|
||||
/// <summary></summary>
|
||||
public static void SuspendDrawing(Windows.UI.Composition.CompositionDrawingSurface drawingSurface) { throw new System.NotImplementedException(); }
|
||||
}
|
||||
|
||||
// This shouldn't be necessary, and it is in the wrong namespace, but it
|
||||
// conflicts with the W.F.Point generated for the numerics docs if it is put
|
||||
// in the right namespace, and it complains that it can't be found if it
|
||||
// isn't present at all.
|
||||
public struct Point { }
|
||||
}
|
|
@ -15,6 +15,7 @@ import "Windows.Graphics.Printing.idl";
|
|||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
import "Windows.UI.Input.Inking.idl";
|
||||
import "Windows.UI.Composition.idl";
|
||||
#endif
|
||||
|
||||
#if WINVER <= _WIN32_WINNT_WINBLUE
|
||||
|
@ -54,6 +55,7 @@ import "Windows.UI.Input.Inking.idl";
|
|||
#include "xaml\CanvasSwapChainPanel.abi.idl"
|
||||
#include "xaml\CanvasVirtualImageSource.abi.idl"
|
||||
#include "xaml\CanvasVirtualControl.abi.idl"
|
||||
#include "composition\CanvasComposition.abi.idl"
|
||||
|
||||
#include "effects\generated\ArithmeticCompositeEffect.abi.idl"
|
||||
#include "effects\generated\AtlasEffect.abi.idl"
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
namespace Microsoft.Graphics.Canvas.UI.Composition
|
||||
{
|
||||
runtimeclass CanvasComposition;
|
||||
|
||||
[version(VERSION), uuid(162DEB43-1CF5-46F8-A0AF-356B23158F92), exclusiveto(CanvasComposition)]
|
||||
interface ICanvasCompositionStatics : IInspectable
|
||||
{
|
||||
//
|
||||
// Compositor interop
|
||||
//
|
||||
|
||||
|
||||
HRESULT CreateCompositionGraphicsDevice(
|
||||
[in] Windows.UI.Composition.Compositor* compositor,
|
||||
[in] Microsoft.Graphics.Canvas.CanvasDevice* canvasDevice,
|
||||
[out, retval] Windows.UI.Composition.CompositionGraphicsDevice** graphicsDevice);
|
||||
|
||||
HRESULT CreateCompositionSurfaceForSwapChain(
|
||||
[in] Windows.UI.Composition.Compositor* compositor,
|
||||
[in] Microsoft.Graphics.Canvas.CanvasSwapChain* swapChain,
|
||||
[out, retval] Windows.UI.Composition.ICompositionSurface** compositionSurface);
|
||||
|
||||
|
||||
//
|
||||
// CompositionGraphicsDevice interop
|
||||
//
|
||||
|
||||
|
||||
HRESULT GetCanvasDevice(
|
||||
[in] Windows.UI.Composition.CompositionGraphicsDevice* graphicsDevice,
|
||||
[out, retval] Microsoft.Graphics.Canvas.CanvasDevice** canvasDevice);
|
||||
|
||||
HRESULT SetCanvasDevice(
|
||||
[in] Windows.UI.Composition.CompositionGraphicsDevice* graphicsDevice,
|
||||
[in] Microsoft.Graphics.Canvas.CanvasDevice* canvasDevice);
|
||||
|
||||
|
||||
//
|
||||
// CompositionDrawingSurface interop
|
||||
//
|
||||
|
||||
|
||||
// NOTE: no ClearColor here. It's up to apps to decide if they want to
|
||||
// clear or if they want to just draw over the entire region. (Differs
|
||||
// from CanvasImageSource where we apply this policy).
|
||||
[overload("CreateDrawingSession")]
|
||||
HRESULT CreateDrawingSession(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface,
|
||||
[out, retval] Microsoft.Graphics.Canvas.CanvasDrawingSession** drawingSession);
|
||||
|
||||
[overload("CreateDrawingSession")]
|
||||
HRESULT CreateDrawingSessionWithUpdateRect(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface,
|
||||
[in] Windows.Foundation.Rect updateRect,
|
||||
[out, retval] Microsoft.Graphics.Canvas.CanvasDrawingSession** drawingSession);
|
||||
|
||||
HRESULT SuspendDrawing(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface);
|
||||
|
||||
HRESULT ResumeDrawing(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface);
|
||||
|
||||
|
||||
// QUESTION: Why isn't this on CompositionDrawingSurface's interface?
|
||||
//
|
||||
// NOTE: sizeInPixels is converted to integer by rounding (rather than
|
||||
// truncating). This is to match the behavior of CreateDrawingSurface.
|
||||
HRESULT Resize(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface,
|
||||
[in] Windows.Foundation.Size sizeInPixels);
|
||||
|
||||
// QUESTION: Why isn't this on CompositionDrawingSurface's interface?
|
||||
//
|
||||
// NOTE: Rects are converted to RECTs by converting first to l,r,t,b and
|
||||
// then rounding. Points are converted by rounding. This is to try and
|
||||
// match CreateDrawingSurface's behavior.
|
||||
HRESULT Scroll(
|
||||
[in] Windows.UI.Composition.CompositionDrawingSurface* drawingSurface,
|
||||
[in] Windows.Foundation.IReference<Windows.Foundation.Rect>* scrollRect,
|
||||
[in] Windows.Foundation.IReference<Windows.Foundation.Rect>* clipRect,
|
||||
[in] Windows.Foundation.Point offset);
|
||||
}
|
||||
|
||||
[version(VERSION), static(ICanvasCompositionStatics, VERSION)]
|
||||
runtimeclass CanvasComposition
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,287 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
#include "CanvasComposition.h"
|
||||
|
||||
#include "../utils/ApiInformationAdapter.h"
|
||||
|
||||
using namespace ABI::Microsoft::Graphics::Canvas::UI::Composition;
|
||||
using namespace ABI::Windows::UI::Composition;
|
||||
|
||||
|
||||
ActivatableStaticOnlyFactory(CanvasCompositionStatics);
|
||||
|
||||
|
||||
HRESULT CanvasCompositionStatics::RuntimeClassInitialize()
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
//
|
||||
// The composition APIs are only available when the Universal API
|
||||
// Contract v2 is present. To nip any problems in the bud we
|
||||
// prevent any of the CanvasComposition APIs from being called if
|
||||
// this contract isn't present.
|
||||
//
|
||||
bool compositionApiPresent = ApiInformationAdapter::GetInstance()->IsApiContractPresent(UNIVERSAL_API_CONTRACT, 2);
|
||||
|
||||
if (!compositionApiPresent)
|
||||
ThrowHR(E_NOTIMPL);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::CreateCompositionGraphicsDevice(
|
||||
ICompositor* compositor,
|
||||
ICanvasDevice* canvasDevice,
|
||||
ICompositionGraphicsDevice** graphicsDevice)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(compositor);
|
||||
CheckInPointer(canvasDevice);
|
||||
CheckAndClearOutPointer(graphicsDevice);
|
||||
|
||||
auto d2dDevice = GetWrappedResource<ID2D1Device1>(canvasDevice);
|
||||
auto compositorInterop = As<ICompositorInterop>(compositor);
|
||||
|
||||
ThrowIfFailed(compositorInterop->CreateGraphicsDevice(d2dDevice.Get(), graphicsDevice));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::CreateCompositionSurfaceForSwapChain(
|
||||
ICompositor* compositor,
|
||||
ICanvasSwapChain* swapChain,
|
||||
ICompositionSurface** compositionSurface)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(compositor);
|
||||
CheckInPointer(swapChain);
|
||||
CheckAndClearOutPointer(compositionSurface);
|
||||
|
||||
auto compositorInterop = As<ICompositorInterop>(compositor);
|
||||
auto dxgiSwapChain = GetWrappedResource<IDXGISwapChain>(swapChain);
|
||||
|
||||
ThrowIfFailed(compositorInterop->CreateCompositionSurfaceForSwapChain(dxgiSwapChain.Get(), compositionSurface));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::GetCanvasDevice(
|
||||
ICompositionGraphicsDevice* graphicsDevice,
|
||||
ICanvasDevice** canvasDevice)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(graphicsDevice);
|
||||
CheckAndClearOutPointer(canvasDevice);
|
||||
|
||||
auto interop = As<ICompositionGraphicsDeviceInterop>(graphicsDevice);
|
||||
|
||||
ComPtr<IUnknown> renderingDevice;
|
||||
ThrowIfFailed(interop->GetRenderingDevice(&renderingDevice));
|
||||
|
||||
auto device = ResourceManager::GetOrCreate<ICanvasDevice>(renderingDevice.Get());
|
||||
ThrowIfFailed(device.CopyTo(canvasDevice));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::SetCanvasDevice(
|
||||
ICompositionGraphicsDevice* graphicsDevice,
|
||||
ICanvasDevice* canvasDevice)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(graphicsDevice);
|
||||
CheckInPointer(canvasDevice);
|
||||
|
||||
auto interop = As<ICompositionGraphicsDeviceInterop>(graphicsDevice);
|
||||
auto d2dDevice = GetWrappedResource<ID2D1Device>(canvasDevice);
|
||||
ThrowIfFailed(interop->SetRenderingDevice(d2dDevice.Get()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::CreateDrawingSession(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
ICanvasDrawingSession** drawingSession)
|
||||
{
|
||||
return CreateDrawingSessionImpl(drawingSurface, nullptr, drawingSession);
|
||||
}
|
||||
|
||||
|
||||
static RECT ToRECTForCompositor(Rect const& rect)
|
||||
{
|
||||
RECT r{};
|
||||
r.left = static_cast<LONG>(std::round(rect.X));
|
||||
r.right = static_cast<LONG>(std::round(rect.X + rect.Width));
|
||||
r.top = static_cast<LONG>(std::round(rect.Y));
|
||||
r.bottom = static_cast<LONG>(std::round(rect.Y + rect.Height));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::CreateDrawingSessionWithUpdateRect(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
Rect updateRect,
|
||||
ICanvasDrawingSession** drawingSession)
|
||||
{
|
||||
RECT rect = ToRECTForCompositor(updateRect);
|
||||
|
||||
return CreateDrawingSessionImpl(drawingSurface, &rect, drawingSession);
|
||||
}
|
||||
|
||||
|
||||
class CompositionDrawingSurfaceDrawingSessionAdapter
|
||||
: public DrawingSessionBaseAdapter
|
||||
, private LifespanTracker<CompositionDrawingSurfaceDrawingSessionAdapter>
|
||||
{
|
||||
ComPtr<ICompositionDrawingSurfaceInterop> m_drawingSurface;
|
||||
|
||||
public:
|
||||
CompositionDrawingSurfaceDrawingSessionAdapter(ComPtr<ICompositionDrawingSurfaceInterop>&& drawingSurface)
|
||||
: m_drawingSurface(std::move(drawingSurface))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void EndDraw(ID2D1DeviceContext1*) override
|
||||
{
|
||||
ThrowIfFailed(m_drawingSurface->EndDraw());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CanvasCompositionStatics::CreateDrawingSessionImpl(ICompositionDrawingSurface* drawingSurface, RECT const* updateRect, ICanvasDrawingSession** drawingSession)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(drawingSurface);
|
||||
CheckAndClearOutPointer(drawingSession);
|
||||
|
||||
auto drawingSurfaceInterop = As<ICompositionDrawingSurfaceInterop>(drawingSurface);
|
||||
|
||||
ComPtr<ID2D1DeviceContext> deviceContext;
|
||||
POINT offset;
|
||||
ThrowIfFailed(drawingSurfaceInterop->BeginDraw(updateRect, IID_PPV_ARGS(&deviceContext), &offset));
|
||||
|
||||
deviceContext->SetTransform(D2D1::Matrix3x2F::Translation((float)offset.x, (float)offset.y));
|
||||
|
||||
// Although we could look up the owner using interop, via the
|
||||
// deviceContext, drawing session will do this lazily for us if
|
||||
// anyone actually requests it.
|
||||
ICanvasDevice* owner = nullptr;
|
||||
|
||||
auto newDs = CanvasDrawingSession::CreateNew(
|
||||
As<ID2D1DeviceContext1>(deviceContext).Get(),
|
||||
std::make_shared<CompositionDrawingSurfaceDrawingSessionAdapter>(std::move(drawingSurfaceInterop)),
|
||||
owner,
|
||||
D2D1_POINT_2F{ (float)offset.x, (float)offset.y });
|
||||
ThrowIfFailed(newDs.CopyTo(drawingSession));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::SuspendDrawing(
|
||||
ICompositionDrawingSurface* drawingSurface)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(drawingSurface);
|
||||
|
||||
auto drawingSurfaceInterop = As<ICompositionDrawingSurfaceInterop>(drawingSurface);
|
||||
|
||||
ThrowIfFailed(drawingSurfaceInterop->SuspendDraw());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::ResumeDrawing(
|
||||
ICompositionDrawingSurface* drawingSurface)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(drawingSurface);
|
||||
|
||||
auto drawingSurfaceInterop = As<ICompositionDrawingSurfaceInterop>(drawingSurface);
|
||||
|
||||
ThrowIfFailed(drawingSurfaceInterop->ResumeDraw());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::Resize(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
Size size)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(drawingSurface);
|
||||
|
||||
SIZE newSize{};
|
||||
newSize.cx = static_cast<LONG>(std::round(size.Width));
|
||||
newSize.cy = static_cast<LONG>(std::round(size.Height));
|
||||
|
||||
auto drawingSurfaceInterop = As<ICompositionDrawingSurfaceInterop>(drawingSurface);
|
||||
|
||||
ThrowIfFailed(drawingSurfaceInterop->Resize(newSize));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static RECT MaybeGetRECT(IReference<Rect>* maybeRect)
|
||||
{
|
||||
RECT r{};
|
||||
|
||||
if (!maybeRect)
|
||||
return r;
|
||||
|
||||
Rect rect;
|
||||
ThrowIfFailed(maybeRect->get_Value(&rect));
|
||||
|
||||
return ToRECTForCompositor(rect);
|
||||
}
|
||||
|
||||
|
||||
IFACEMETHODIMP CanvasCompositionStatics::Scroll(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
IReference<Rect>* scrollRect,
|
||||
IReference<Rect>* clipRect,
|
||||
Point offset)
|
||||
{
|
||||
return ExceptionBoundary(
|
||||
[&]
|
||||
{
|
||||
CheckInPointer(drawingSurface);
|
||||
|
||||
RECT scroll = MaybeGetRECT(scrollRect);
|
||||
RECT clip = MaybeGetRECT(clipRect);
|
||||
|
||||
int offsetX = static_cast<int>(std::round(offset.X));
|
||||
int offsetY = static_cast<int>(std::round(offset.Y));
|
||||
|
||||
auto drawingSurfaceInterop = As<ICompositionDrawingSurfaceInterop>(drawingSurface);
|
||||
ThrowIfFailed(drawingSurfaceInterop->Scroll(
|
||||
scrollRect ? &scroll : nullptr,
|
||||
clipRect ? &clip : nullptr,
|
||||
offsetX,
|
||||
offsetY));
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas { namespace UI { namespace Composition
|
||||
{
|
||||
using namespace ABI::Windows::UI::Composition;
|
||||
|
||||
class CanvasCompositionStatics : public ActivationFactory<ICanvasCompositionStatics>
|
||||
{
|
||||
InspectableClassStatic(RuntimeClass_Microsoft_Graphics_Canvas_UI_Composition_CanvasComposition, BaseTrust);
|
||||
|
||||
public:
|
||||
HRESULT RuntimeClassInitialize();
|
||||
|
||||
IFACEMETHODIMP CreateCompositionGraphicsDevice(
|
||||
ICompositor* compositor,
|
||||
ICanvasDevice* canvasDevice,
|
||||
ICompositionGraphicsDevice** graphicsDevice) override;
|
||||
|
||||
IFACEMETHODIMP CreateCompositionSurfaceForSwapChain(
|
||||
ICompositor* compositor,
|
||||
ICanvasSwapChain* swapChain,
|
||||
ICompositionSurface** compositionSurface) override;
|
||||
|
||||
IFACEMETHODIMP GetCanvasDevice(
|
||||
ICompositionGraphicsDevice* graphicsDevice,
|
||||
ICanvasDevice** canvasDevice) override;
|
||||
|
||||
IFACEMETHODIMP SetCanvasDevice(
|
||||
ICompositionGraphicsDevice* graphicsDevice,
|
||||
ICanvasDevice* canvasDevice) override;
|
||||
|
||||
IFACEMETHODIMP CreateDrawingSession(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
ICanvasDrawingSession** drawingSession) override;
|
||||
|
||||
IFACEMETHODIMP CreateDrawingSessionWithUpdateRect(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
Rect updateRect,
|
||||
ICanvasDrawingSession** drawingSession) override;
|
||||
|
||||
IFACEMETHODIMP SuspendDrawing(
|
||||
ICompositionDrawingSurface* drawingSurface) override;
|
||||
|
||||
IFACEMETHODIMP ResumeDrawing(
|
||||
ICompositionDrawingSurface* drawingSurface) override;
|
||||
|
||||
IFACEMETHODIMP Resize(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
Size size) override;
|
||||
|
||||
IFACEMETHODIMP Scroll(
|
||||
ICompositionDrawingSurface* drawingSurface,
|
||||
IReference<Rect>* scrollRect,
|
||||
IReference<Rect>* clipRect,
|
||||
Point offset) override;
|
||||
|
||||
private:
|
||||
HRESULT CreateDrawingSessionImpl(ICompositionDrawingSurface* drawingSurface, RECT const* rect, ICanvasDrawingSession** drawingSession);
|
||||
};
|
||||
|
||||
} } } } } }
|
||||
|
||||
#endif
|
|
@ -69,6 +69,12 @@
|
|||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
#include <windows.graphics.display.h>
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
#include <windows.foundation.metadata.h>
|
||||
#include <windows.ui.composition.h>
|
||||
#include <windows.ui.composition.interop.h>
|
||||
#endif
|
||||
|
||||
#pragma warning(default: 4265) // "class has virtual functions, but destructor is not virtual"
|
||||
|
||||
// Public
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
#include "ApiInformationAdapter.h"
|
||||
|
||||
using namespace ABI::Windows::Foundation::Metadata;
|
||||
|
||||
bool DefaultApiInformationAdapter::IsApiContractPresent(wchar_t const* contractName, int majorVersion)
|
||||
{
|
||||
assert(majorVersion >= 0 && majorVersion <= 0xFF);
|
||||
|
||||
ComPtr<IApiInformationStatics> apiInformation;
|
||||
ThrowIfFailed(GetActivationFactory(
|
||||
HStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(),
|
||||
&apiInformation));
|
||||
|
||||
boolean isPresent;
|
||||
ThrowIfFailed(apiInformation->IsApiContractPresentByMajor(
|
||||
HStringReference(contractName).Get(),
|
||||
static_cast<uint16_t>(majorVersion),
|
||||
&isPresent));
|
||||
|
||||
return !!isPresent;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class DefaultApiInformationAdapter;
|
||||
|
||||
static wchar_t const* UNIVERSAL_API_CONTRACT = L"Windows.Foundation.UniversalApiContract";
|
||||
|
||||
//
|
||||
// Adapter for accessing information about which APIs are present on the system
|
||||
// via Windows.Foundation.Metadata.ApiInformation.
|
||||
//
|
||||
class ApiInformationAdapter : public Singleton<ApiInformationAdapter, DefaultApiInformationAdapter>
|
||||
{
|
||||
public:
|
||||
virtual ~ApiInformationAdapter() = default;
|
||||
|
||||
virtual bool IsApiContractPresent(wchar_t const* contractName, int majorVersion) = 0;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Default implementation of ApiInformationAdapter calls through to
|
||||
// Windows.Foundation.Metadata.ApiInformation.
|
||||
//
|
||||
class DefaultApiInformationAdapter : public ApiInformationAdapter
|
||||
{
|
||||
public:
|
||||
virtual bool IsApiContractPresent(wchar_t const* contractName, int majorVersion) override;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
|
@ -45,6 +45,7 @@
|
|||
<Exec Command="$(MdMergeExe) -v @(MetaDataDir -> '-metadata_dir "%(Identity)"', ' ') -o "$(MergedWinmdDirectory)" -i "$(UnmergedWinmdDirectory)" -partial -n:Microsoft.Graphics.Canvas:3" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)drawing\CanvasActiveLayer.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)drawing\DeviceContextPool.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)effects\generated\ChromaKeyEffect.h" />
|
||||
|
@ -78,6 +79,7 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)printing\CanvasPrintTaskOptionsChangedEventArgs.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)printing\DeferrableTask.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)printing\DeferrableTaskScheduler.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\ApiInformationAdapter.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\CachedResourceReference.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\LockUtilities.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\TemporaryTransform.h" />
|
||||
|
@ -166,6 +168,7 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\Strings.inl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)effects\generated\ChromaKeyEffect.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)effects\generated\ContrastEffect.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)effects\generated\EdgeDetectionEffect.cpp" />
|
||||
|
@ -197,6 +200,7 @@
|
|||
<ClCompile Include="$(MSBuildThisFileDirectory)printing\CanvasPrintDocumentAdapter.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)printing\CanvasPrintEventArgs.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)printing\DeferrableTask.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)utils\ApiInformationAdapter.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)utils\ResourceManager.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)xaml\CanvasAnimatedControl.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)xaml\CanvasAnimatedControlAdapter.cpp" />
|
||||
|
@ -278,6 +282,7 @@
|
|||
</MidlRT>
|
||||
<None Include="$(MSBuildThisFileDirectory)Canvas.codegen.idl" />
|
||||
<None Include="$(MSBuildThisFileDirectory)brushes\CanvasBrush.abi.idl" />
|
||||
<None Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.abi.idl" />
|
||||
<None Include="$(MSBuildThisFileDirectory)xaml\CanvasAnimatedControl.abi.idl" />
|
||||
<None Include="$(MSBuildThisFileDirectory)xaml\CanvasControl.abi.idl" />
|
||||
<None Include="$(MSBuildThisFileDirectory)xaml\CanvasImageSource.abi.idl" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="effects">
|
||||
|
@ -34,6 +34,9 @@
|
|||
<Filter Include="printing">
|
||||
<UniqueIdentifier>{007da80b-0c24-4f3a-a5be-1ec320c18646}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="composition">
|
||||
<UniqueIdentifier>{6833e68e-c2a4-4af0-a737-aa8e537554c8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MidlRT Include="$(MSBuildThisFileDirectory)Canvas.abi.idl" />
|
||||
|
@ -346,6 +349,12 @@
|
|||
<ClCompile Include="$(MSBuildThisFileDirectory)printing\DeferrableTask.cpp">
|
||||
<Filter>printing</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.cpp">
|
||||
<Filter>composition</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)utils\ApiInformationAdapter.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)pch.h" />
|
||||
|
@ -703,6 +712,12 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)printing\DeferrableTaskScheduler.h">
|
||||
<Filter>printing</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.h">
|
||||
<Filter>composition</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\ApiInformationAdapter.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)Canvas.codegen.idl" />
|
||||
|
@ -949,5 +964,8 @@
|
|||
<None Include="$(MSBuildThisFileDirectory)printing\CanvasPrintDocument.abi.idl">
|
||||
<Filter>printing</Filter>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)composition\CanvasComposition.abi.idl">
|
||||
<Filter>composition</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,432 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
#include <lib/composition/CanvasComposition.h>
|
||||
|
||||
using namespace ABI::Microsoft::Graphics::Canvas::UI::Composition;
|
||||
|
||||
static int const AnyOffsetX = 123;
|
||||
static int const AnyOffsetY = -456;
|
||||
static HRESULT const AnyErrorResult = 0x81234567;
|
||||
|
||||
|
||||
static ComPtr<ICanvasCompositionStatics> GetCompositionStatics()
|
||||
{
|
||||
ComPtr<ICanvasCompositionStatics> composition;
|
||||
ThrowIfFailed(MakeAndInitialize<CanvasCompositionStatics>(&composition));
|
||||
return composition;
|
||||
}
|
||||
|
||||
|
||||
TEST_CLASS(CanvasCompositionUnitTests)
|
||||
{
|
||||
public:
|
||||
struct Fixture
|
||||
{
|
||||
std::shared_ptr<ApiInformationTestAdapter> ApiInformation = ApiInformationTestAdapter::Create();
|
||||
ComPtr<ICanvasCompositionStatics> Composition;
|
||||
|
||||
Fixture()
|
||||
{
|
||||
ApiInformation->AddContract(UNIVERSAL_API_CONTRACT, 2);
|
||||
Composition = GetCompositionStatics();
|
||||
}
|
||||
|
||||
Fixture(Fixture const&) = delete;
|
||||
Fixture& operator=(Fixture const&) = delete;
|
||||
};
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateCompositionGraphicsDevice_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto compositor = Make<MockCompositor>();
|
||||
auto canvasDevice = Make<MockCanvasDevice>();
|
||||
ComPtr<ICompositionGraphicsDevice> graphicsDevice;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionGraphicsDevice(nullptr, canvasDevice.Get(), &graphicsDevice));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionGraphicsDevice(compositor.Get(), nullptr, &graphicsDevice));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionGraphicsDevice(compositor.Get(), canvasDevice.Get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateCompositionGraphicsDevice)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto compositor = Make<MockCompositor>();
|
||||
auto d2dDevice = Make<StubD2DDevice>();
|
||||
auto canvasDevice = Make<CanvasDevice>(d2dDevice.Get());
|
||||
auto graphicsDevice = Make<MockCompositionGraphicsDevice>();
|
||||
|
||||
compositor->CreateGraphicsDeviceMethod.SetExpectedCalls(1,
|
||||
[&] (IUnknown* renderingDevice, ICompositionGraphicsDevice** value)
|
||||
{
|
||||
Assert::IsTrue(IsSameInstance(d2dDevice.Get(), renderingDevice));
|
||||
return graphicsDevice.CopyTo(value);
|
||||
});
|
||||
|
||||
ComPtr<ICompositionGraphicsDevice> actualGraphicsDevice;
|
||||
ThrowIfFailed(f.Composition->CreateCompositionGraphicsDevice(compositor.Get(), canvasDevice.Get(), &actualGraphicsDevice));
|
||||
|
||||
Assert::IsTrue(IsSameInstance(graphicsDevice.Get(), actualGraphicsDevice.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateCompositionSurfaceForSwapChain_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto compositor = Make<MockCompositor>();
|
||||
auto swapChain = Make<MockCanvasSwapChain>();
|
||||
ComPtr<ICompositionSurface> compositionSurface;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionSurfaceForSwapChain(nullptr, swapChain.Get(), &compositionSurface));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionSurfaceForSwapChain(compositor.Get(), nullptr, &compositionSurface));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateCompositionSurfaceForSwapChain(compositor.Get(), swapChain.Get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateCompositionSurfaceForSwapChain)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto compositor = Make<MockCompositor>();
|
||||
auto dxgiSwapChain = Make<MockDxgiSwapChain>();
|
||||
auto canvasDevice = Make<MockCanvasDevice>();
|
||||
auto canvasSwapChain = Make<CanvasSwapChain>(canvasDevice.Get(), dxgiSwapChain.Get(), DEFAULT_DPI, false);
|
||||
auto compositionSurface = Make<RuntimeClass<ICompositionSurface>>();
|
||||
|
||||
compositor->CreateCompositionSurfaceForSwapChainMethod.SetExpectedCalls(1,
|
||||
[&] (IUnknown* swapChain, ICompositionSurface** value)
|
||||
{
|
||||
Assert::IsTrue(IsSameInstance(dxgiSwapChain.Get(), swapChain));
|
||||
return compositionSurface.CopyTo(value);
|
||||
});
|
||||
|
||||
ComPtr<ICompositionSurface> actualCompositionSurface;
|
||||
ThrowIfFailed(f.Composition->CreateCompositionSurfaceForSwapChain(compositor.Get(), canvasSwapChain.Get(), &actualCompositionSurface));
|
||||
|
||||
Assert::IsTrue(IsSameInstance(compositionSurface.Get(), actualCompositionSurface.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_GetCanvasDevice_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto graphicsDevice = Make<MockCompositionGraphicsDevice>();
|
||||
ComPtr<ICanvasDevice> canvasDevice;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->GetCanvasDevice(nullptr, &canvasDevice));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->GetCanvasDevice(graphicsDevice.Get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_GetCanvasDevice)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto graphicsDevice = Make<MockCompositionGraphicsDevice>();
|
||||
auto d2dDevice = Make<StubD2DDevice>();
|
||||
auto canvasDevice = Make<CanvasDevice>(d2dDevice.Get());
|
||||
|
||||
graphicsDevice->GetRenderingDeviceMethod.SetExpectedCalls(1,
|
||||
[&] (IUnknown** value)
|
||||
{
|
||||
return d2dDevice.CopyTo(value);
|
||||
});
|
||||
|
||||
ComPtr<ICanvasDevice> actualCanvasDevice;
|
||||
ThrowIfFailed(f.Composition->GetCanvasDevice(graphicsDevice.Get(), &actualCanvasDevice));
|
||||
|
||||
Assert::IsTrue(IsSameInstance(canvasDevice.Get(), actualCanvasDevice.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_SetCanvasDevice_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto graphicsDevice = Make<MockCompositionGraphicsDevice>();
|
||||
auto canvasDevice = Make<MockCanvasDevice>();
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->SetCanvasDevice(nullptr, canvasDevice.Get()));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->SetCanvasDevice(graphicsDevice.Get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_SetCanvasDevice)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto graphicsDevice = Make<MockCompositionGraphicsDevice>();
|
||||
auto d2dDevice = Make<StubD2DDevice>();
|
||||
auto canvasDevice = Make<CanvasDevice>(d2dDevice.Get());
|
||||
|
||||
graphicsDevice->SetRenderingDeviceMethod.SetExpectedCalls(1,
|
||||
[&] (IUnknown* value)
|
||||
{
|
||||
Assert::IsTrue(IsSameInstance(d2dDevice.Get(), value));
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
ThrowIfFailed(f.Composition->SetCanvasDevice(graphicsDevice.Get(), canvasDevice.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateDrawingSession_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
auto drawingSurface = Make<MockCompositionDrawingSurface>();
|
||||
ComPtr<ICanvasDrawingSession> drawingSession;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateDrawingSession(nullptr, &drawingSession));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateDrawingSession(drawingSurface.Get(), nullptr));
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateDrawingSessionWithUpdateRect(nullptr, Rect{}, &drawingSession));
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->CreateDrawingSessionWithUpdateRect(drawingSurface.Get(), Rect{}, nullptr));
|
||||
}
|
||||
|
||||
struct DrawingSurfaceFixture : public Fixture
|
||||
{
|
||||
ComPtr<MockCompositionDrawingSurface> DrawingSurface = Make<MockCompositionDrawingSurface>();
|
||||
};
|
||||
|
||||
struct DrawingSessionFixture : public DrawingSurfaceFixture
|
||||
{
|
||||
ComPtr<StubD2DDeviceContext> D2DDeviceContext = Make<StubD2DDeviceContext>();
|
||||
|
||||
DrawingSessionFixture()
|
||||
{
|
||||
D2DDeviceContext->SetTransformMethod.SetExpectedCalls(1,
|
||||
[&] (D2D1_MATRIX_3X2_F const* m)
|
||||
{
|
||||
Assert::AreEqual(1.0f, m->_11);
|
||||
Assert::AreEqual(0.0f, m->_12);
|
||||
Assert::AreEqual(0.0f, m->_21);
|
||||
Assert::AreEqual(1.0f, m->_22);
|
||||
Assert::AreEqual((float)AnyOffsetX, m->_31);
|
||||
Assert::AreEqual((float)AnyOffsetY, m->_32);
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT DoBeginDraw(REFIID iid, void** updateObject, POINT* updateOffset)
|
||||
{
|
||||
Assert::AreEqual(__uuidof(ID2D1DeviceContext), iid);
|
||||
ThrowIfFailed(D2DDeviceContext.CopyTo(iid, updateObject));
|
||||
|
||||
*updateOffset = POINT{ AnyOffsetX, AnyOffsetY };
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Check(ComPtr<ICanvasDrawingSession> drawingSession)
|
||||
{
|
||||
auto actualDeviceContext = GetWrappedResource<ID2D1DeviceContext1>(drawingSession);
|
||||
Assert::IsTrue(IsSameInstance(D2DDeviceContext.Get(), actualDeviceContext.Get()));
|
||||
|
||||
// the return value from EndDraw should be passed back through Close()
|
||||
DrawingSurface->EndDrawMethod.SetExpectedCalls(1,
|
||||
[&]
|
||||
{
|
||||
return AnyErrorResult;
|
||||
});
|
||||
Assert::AreEqual(AnyErrorResult, As<IClosable>(drawingSession)->Close());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateDrawingSession)
|
||||
{
|
||||
DrawingSessionFixture f;
|
||||
|
||||
f.DrawingSurface->BeginDrawMethod.SetExpectedCalls(1,
|
||||
[&] (const RECT* updateRect, REFIID iid, void** updateObject, POINT* updateOffset)
|
||||
{
|
||||
Assert::IsNull(updateRect);
|
||||
return f.DoBeginDraw(iid, updateObject, updateOffset);
|
||||
});
|
||||
|
||||
ComPtr<ICanvasDrawingSession> drawingSession;
|
||||
ThrowIfFailed(f.Composition->CreateDrawingSession(f.DrawingSurface.Get(), &drawingSession));
|
||||
|
||||
f.Check(drawingSession);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_CreateDrawingSessionWithUpdateRect)
|
||||
{
|
||||
DrawingSessionFixture f;
|
||||
|
||||
Rect anyRect{};
|
||||
anyRect.X = 1.1f;
|
||||
anyRect.Y = 2.1f;
|
||||
anyRect.Width = 3.1f;
|
||||
anyRect.Height = 4.4f;
|
||||
|
||||
RECT anyRECT;
|
||||
anyRECT.left = 1;
|
||||
anyRECT.right = 4; // (1.1 + 3.1) = (4.2) - Composition rounds, so this becomes 4
|
||||
anyRECT.top = 2;
|
||||
anyRECT.bottom = 7; // (2.1 + 4.4) = (6.5) - Composition rounds, so this becomes 7.
|
||||
|
||||
f.DrawingSurface->BeginDrawMethod.SetExpectedCalls(1,
|
||||
[&] (const RECT* updateRect, REFIID iid, void** updateObject, POINT* updateOffset)
|
||||
{
|
||||
Assert::IsNotNull(updateRect);
|
||||
Assert::AreEqual(anyRECT, *updateRect);
|
||||
return f.DoBeginDraw(iid, updateObject, updateOffset);
|
||||
});
|
||||
|
||||
ComPtr<ICanvasDrawingSession> drawingSession;
|
||||
ThrowIfFailed(f.Composition->CreateDrawingSessionWithUpdateRect(f.DrawingSurface.Get(), anyRect, &drawingSession));
|
||||
|
||||
f.Check(drawingSession);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_SuspendDrawing_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->SuspendDrawing(nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_SuspendDrawing)
|
||||
{
|
||||
DrawingSurfaceFixture f;
|
||||
|
||||
f.DrawingSurface->SuspendDrawMethod.SetExpectedCalls(1,
|
||||
[]
|
||||
{
|
||||
return AnyErrorResult;
|
||||
});
|
||||
Assert::AreEqual(AnyErrorResult, f.Composition->SuspendDrawing(f.DrawingSurface.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_ResumeDrawing_FailsWhenPassedNullParameters)
|
||||
{
|
||||
Fixture f;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->ResumeDrawing(nullptr));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_ResumeDrawing)
|
||||
{
|
||||
DrawingSurfaceFixture f;
|
||||
|
||||
f.DrawingSurface->ResumeDrawMethod.SetExpectedCalls(1,
|
||||
[]
|
||||
{
|
||||
return AnyErrorResult;
|
||||
});
|
||||
Assert::AreEqual(AnyErrorResult, f.Composition->ResumeDrawing(f.DrawingSurface.Get()));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Resize_FailsWhenPassedNullParameters)
|
||||
{
|
||||
DrawingSurfaceFixture f;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->Resize(nullptr, Size{}));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Resize)
|
||||
{
|
||||
DrawingSurfaceFixture f;
|
||||
|
||||
Size anySize{ 12.49f, 12.50f };
|
||||
SIZE expectedSIZE{ 12, 13 }; // Compositor rounds rather than truncates
|
||||
|
||||
f.DrawingSurface->ResizeMethod.SetExpectedCalls(1,
|
||||
[&] (SIZE size)
|
||||
{
|
||||
Assert::AreEqual(expectedSIZE.cx, size.cx);
|
||||
Assert::AreEqual(expectedSIZE.cy, size.cy);
|
||||
return AnyErrorResult;
|
||||
});
|
||||
Assert::AreEqual(AnyErrorResult, f.Composition->Resize(f.DrawingSurface.Get(), anySize));
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Scroll_FailsWhenPassedNullParameters)
|
||||
{
|
||||
DrawingSurfaceFixture f;
|
||||
|
||||
IReference<Rect>* nullScrollRectIsValid = nullptr;
|
||||
IReference<Rect>* nullClipRectIsValid = nullptr;
|
||||
|
||||
Assert::AreEqual(E_INVALIDARG, f.Composition->Scroll(nullptr, nullScrollRectIsValid, nullClipRectIsValid, Point{}));
|
||||
}
|
||||
|
||||
struct ScrollFixture : public DrawingSurfaceFixture
|
||||
{
|
||||
Rect ScrollRectValue{ 1.1f, 1.4f, 2.3f, 2.1f };
|
||||
Rect ClipRectValue{ 3.4f, 3.4f, 4.1f, 4.0f };
|
||||
|
||||
RECT ExpectedScrollRect{ 1, 1, 3, 4 };
|
||||
RECT ExpectedClipRect{ 3, 3, 8, 7 };
|
||||
|
||||
ComPtr<IReference<Rect>> ScrollRect = Make<Nullable<Rect>>(ScrollRectValue);
|
||||
ComPtr<IReference<Rect>> ClipRect = Make<Nullable<Rect>>(ClipRectValue);
|
||||
|
||||
void Test(bool scroll, bool clip)
|
||||
{
|
||||
Point offset{ -1.5f, 1.5f };
|
||||
int expectedOffsetX = -2;
|
||||
int expectedOffsetY = 2;
|
||||
|
||||
DrawingSurface->ScrollMethod.SetExpectedCalls(1,
|
||||
[=] (RECT const* scrollRect, RECT const* clipRect, int offsetX, int offsetY)
|
||||
{
|
||||
if (scroll)
|
||||
Assert::AreEqual(ExpectedScrollRect, *scrollRect);
|
||||
else
|
||||
Assert::IsNull(scrollRect);
|
||||
|
||||
if (clip)
|
||||
Assert::AreEqual(ExpectedClipRect, *clipRect);
|
||||
else
|
||||
Assert::IsNull(clipRect);
|
||||
|
||||
Assert::AreEqual(expectedOffsetX, offsetX);
|
||||
Assert::AreEqual(expectedOffsetY, offsetY);
|
||||
|
||||
return AnyErrorResult;
|
||||
});
|
||||
|
||||
Assert::AreEqual(AnyErrorResult, Composition->Scroll(
|
||||
DrawingSurface.Get(),
|
||||
scroll ? ScrollRect.Get() : nullptr,
|
||||
clip ? ClipRect.Get() : nullptr,
|
||||
offset));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Scroll_NoRects)
|
||||
{
|
||||
ScrollFixture f;
|
||||
f.Test(false, false);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Scroll_ScrollRect)
|
||||
{
|
||||
ScrollFixture f;
|
||||
f.Test(true, false);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Scroll_ClipRect)
|
||||
{
|
||||
ScrollFixture f;
|
||||
f.Test(false, true);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_Scroll_ScrollRectAndClipRect)
|
||||
{
|
||||
ScrollFixture f;
|
||||
f.Test(true, true);
|
||||
}
|
||||
|
||||
TEST_METHOD_EX(CanvasComposition_When_CompositionApiNotPresent_CannotActivate)
|
||||
{
|
||||
auto apiInformation = ApiInformationTestAdapter::Create();
|
||||
|
||||
ExpectHResultException(E_NOTIMPL, [] { GetCompositionStatics(); });
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
class MockCompositionDrawingSurface : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
|
||||
ICompositionDrawingSurface,
|
||||
ICompositionDrawingSurfaceInterop>
|
||||
{
|
||||
public:
|
||||
// ICompositionDrawingSurface
|
||||
MOCK_METHOD1(get_AlphaMode , HRESULT(DirectXAlphaMode* value));
|
||||
MOCK_METHOD1(get_PixelFormat , HRESULT(DirectXPixelFormat* value));
|
||||
MOCK_METHOD1(get_Size , HRESULT(Size *value));
|
||||
|
||||
// ICompositionDrawingSurfaceInterop
|
||||
MOCK_METHOD4(BeginDraw, HRESULT(const RECT* updateRect, REFIID iid, void** updateObject, POINT* updateOffset));
|
||||
MOCK_METHOD0(EndDraw, HRESULT());
|
||||
MOCK_METHOD1(Resize, HRESULT(SIZE pixelSize));
|
||||
MOCK_METHOD4(Scroll, HRESULT(const RECT* scrollRect, const RECT* clipRect, int offsetX, int offsetY));
|
||||
MOCK_METHOD0(ResumeDraw, HRESULT());
|
||||
MOCK_METHOD0(SuspendDraw, HRESULT());
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
class MockCompositionGraphicsDevice : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
|
||||
ICompositionGraphicsDevice,
|
||||
ICompositionGraphicsDeviceInterop>
|
||||
{
|
||||
public:
|
||||
// ICompositionGraphicsDevice
|
||||
MOCK_METHOD4(CreateDrawingSurface, HRESULT(Size sizePixels, DirectXPixelFormat pixelFormat, DirectXAlphaMode alphaMode, ICompositionDrawingSurface** result));
|
||||
MOCK_METHOD2(add_RenderingDeviceReplaced, HRESULT(ITypedEventHandler<CompositionGraphicsDevice*, RenderingDeviceReplacedEventArgs*>* handler, EventRegistrationToken *token));
|
||||
MOCK_METHOD1(remove_RenderingDeviceReplaced, HRESULT(EventRegistrationToken token));
|
||||
|
||||
// ICompositionGraphicsDeviceInterop
|
||||
MOCK_METHOD1(GetRenderingDevice, HRESULT(IUnknown** ppBackingDevice));
|
||||
MOCK_METHOD1(SetRenderingDevice, HRESULT(IUnknown* pBackingDevice));
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
using namespace ABI::Windows::UI::Composition;
|
||||
|
||||
class MockCompositor : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
|
||||
ICompositor,
|
||||
ICompositorInterop>
|
||||
{
|
||||
public:
|
||||
// ICompositor
|
||||
MOCK_METHOD1(CreateColorKeyFrameAnimation , HRESULT(IColorKeyFrameAnimation** result));
|
||||
MOCK_METHOD1(CreateColorBrush , HRESULT(ICompositionColorBrush** result));
|
||||
MOCK_METHOD2(CreateColorBrushWithColor , HRESULT(Color color, ICompositionColorBrush** result));
|
||||
MOCK_METHOD1(CreateContainerVisual , HRESULT(IContainerVisual** result));
|
||||
MOCK_METHOD3(CreateCubicBezierEasingFunction , HRESULT(Vector2 controlPoint1, Vector2 controlPoint2, ICubicBezierEasingFunction** result));
|
||||
MOCK_METHOD2(CreateEffectFactory , HRESULT(IGraphicsEffect* graphicsEffect, ICompositionEffectFactory** result));
|
||||
MOCK_METHOD3(CreateEffectFactoryWithProperties , HRESULT(IGraphicsEffect* graphicsEffect, IIterable<HSTRING>* animatableProperties, ICompositionEffectFactory* *result));
|
||||
MOCK_METHOD1(CreateExpressionAnimation , HRESULT(IExpressionAnimation** result));
|
||||
MOCK_METHOD2(CreateExpressionAnimationWithExpression , HRESULT(HSTRING expression, IExpressionAnimation** result));
|
||||
MOCK_METHOD1(CreateInsetClip , HRESULT(IInsetClip** result));
|
||||
MOCK_METHOD5(CreateInsetClipWithInsets , HRESULT(FLOAT leftInset, FLOAT topInset, FLOAT rightInset, FLOAT bottomInset, IInsetClip** result));
|
||||
MOCK_METHOD1(CreateLinearEasingFunction , HRESULT(ILinearEasingFunction** result));
|
||||
MOCK_METHOD1(CreatePropertySet , HRESULT(ICompositionPropertySet** result));
|
||||
MOCK_METHOD1(CreateQuaternionKeyFrameAnimation , HRESULT(IQuaternionKeyFrameAnimation** result));
|
||||
MOCK_METHOD1(CreateScalarKeyFrameAnimation , HRESULT(IScalarKeyFrameAnimation** result));
|
||||
MOCK_METHOD2(CreateScopedBatch , HRESULT(CompositionBatchTypes batchType, ICompositionScopedBatch** result));
|
||||
MOCK_METHOD1(CreateSpriteVisual , HRESULT(ISpriteVisual** result));
|
||||
MOCK_METHOD1(CreateSurfaceBrush , HRESULT(ICompositionSurfaceBrush** result));
|
||||
MOCK_METHOD2(CreateSurfaceBrushWithSurface , HRESULT(ICompositionSurface* surface, ICompositionSurfaceBrush** result));
|
||||
MOCK_METHOD1(CreateTargetForCurrentView , HRESULT(ABI::Windows::UI::Composition::ICompositionTarget** result));
|
||||
MOCK_METHOD1(CreateVector2KeyFrameAnimation , HRESULT(IVector2KeyFrameAnimation** result));
|
||||
MOCK_METHOD1(CreateVector3KeyFrameAnimation , HRESULT(IVector3KeyFrameAnimation** result));
|
||||
MOCK_METHOD1(CreateVector4KeyFrameAnimation , HRESULT(IVector4KeyFrameAnimation** result));
|
||||
MOCK_METHOD2(GetCommitBatch , HRESULT(CompositionBatchTypes batchType, ICompositionCommitBatch** result));
|
||||
|
||||
// ICompositorInterop
|
||||
MOCK_METHOD2(CreateCompositionSurfaceForHandle , HRESULT(HANDLE hDxgiSwapChain, ICompositionSurface** value));
|
||||
MOCK_METHOD2(CreateCompositionSurfaceForSwapChain , HRESULT(IUnknown* pDxgiSwapChain, ICompositionSurface** value));
|
||||
MOCK_METHOD2(CreateGraphicsDevice , HRESULT(IUnknown* pRenderingDevice, ICompositionGraphicsDevice** value));
|
||||
};
|
||||
|
||||
#endif
|
|
@ -25,9 +25,13 @@ using namespace ABI::Microsoft::Graphics::Canvas::Effects;
|
|||
#include "../test.external/MockDxgiSurface.h"
|
||||
|
||||
#include "utils/Helpers.h"
|
||||
#include "utils/ApiInformationTestAdapter.h"
|
||||
#include "mocks/MockHelpers.h"
|
||||
#include "mocks/MockAsyncAction.h"
|
||||
#include "mocks/MockDxgiSwapChain.h"
|
||||
#include "mocks/MockCompositor.h"
|
||||
#include "mocks/MockCompositionGraphicsDevice.h"
|
||||
#include "mocks/MockCompositionDrawingSurface.h"
|
||||
#include "mocks/MockCanvasDevice.h"
|
||||
#include "mocks/MockCanvasDrawingSession.h"
|
||||
#include "mocks/MockCanvasImageSourceDrawingSessionFactory.h"
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WINVER > _WIN32_WINNT_WINBLUE
|
||||
|
||||
#include <lib/utils/ApiInformationAdapter.h>
|
||||
|
||||
class ApiInformationTestAdapter : public ApiInformationAdapter
|
||||
{
|
||||
std::vector<std::pair<std::wstring, int>> m_contracts;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<ApiInformationTestAdapter> Create()
|
||||
{
|
||||
auto adapter = std::make_shared<ApiInformationTestAdapter>();
|
||||
ApiInformationAdapter::SetInstance(adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
ApiInformationTestAdapter()
|
||||
{
|
||||
AddContract(UNIVERSAL_API_CONTRACT, 1);
|
||||
}
|
||||
|
||||
void AddContract(wchar_t const* contractName, int majorVersion)
|
||||
{
|
||||
m_contracts.push_back({contractName, majorVersion});
|
||||
}
|
||||
|
||||
virtual bool IsApiContractPresent(wchar_t const* contractName, int majorVersion)
|
||||
{
|
||||
std::pair<std::wstring, int> toFind(contractName, majorVersion);
|
||||
return (std::find(m_contracts.begin(), m_contracts.end(), toFind) != m_contracts.end());
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
|
@ -23,6 +23,9 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCanvasVirtualImageSource.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositionDrawingSurface.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositionGraphicsDevice.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositor.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCoreWindow.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockD2DEllipseGeometry.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockD2DRectangleGeometry.h" />
|
||||
|
@ -41,6 +44,7 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)stubs\StubResourceCreatorWithDpi.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)stubs\StubStorageFile.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)stubs\StubStorageFileStatics.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\ApiInformationTestAdapter.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)xaml\BaseControlTestAdapter.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)xaml\BasicControlFixture.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)xaml\CanvasAnimatedControlTestAdapter.h" />
|
||||
|
@ -124,6 +128,7 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)xaml\StubDispatcher.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)composition\CanvasCompositionUnitTests.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)graphics\CanvasPrintDocumentUnitTests.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="xaml">
|
||||
|
@ -16,6 +16,9 @@
|
|||
<Filter Include="stubs">
|
||||
<UniqueIdentifier>{c531b9c2-9295-431a-a302-c74e2f1730b4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="composition">
|
||||
<UniqueIdentifier>{7b54d51e-b689-4225-87a4-c1f1995ccd9b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)pch.cpp" />
|
||||
|
@ -151,6 +154,9 @@
|
|||
<ClCompile Include="$(MSBuildThisFileDirectory)graphics\CanvasTextRenderingParametersUnitTests.cpp">
|
||||
<Filter>graphics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)composition\CanvasCompositionUnitTests.cpp">
|
||||
<Filter>composition</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)pch.h" />
|
||||
|
@ -457,6 +463,18 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockPrintTaskOptions.h">
|
||||
<Filter>mocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositor.h">
|
||||
<Filter>mocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositionDrawingSurface.h">
|
||||
<Filter>mocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)mocks\MockCompositionGraphicsDevice.h">
|
||||
<Filter>mocks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utils\ApiInformationTestAdapter.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="$(MSBuildThisFileDirectory)readme.txt" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче