From 1a87b8d6fa113c31a2641c65a896da26d63ff5da Mon Sep 17 00:00:00 2001 From: Simeon Date: Mon, 28 Oct 2019 10:49:42 -0700 Subject: [PATCH] Generate version-dependent code. (#165) Support codegen of multiple versions to allow runtime switching based on the current platform. --- source/UIData/CodeGen/AnimatedVisualInfo.cs | 47 ----- .../CodeGen/CSharpInstantiatorGenerator.cs | 98 ++++++++--- .../UIData/CodeGen/CxInstantiatorGenerator.cs | 90 +++++++--- source/UIData/CodeGen/IAnimatedVisualInfo.cs | 43 +++++ ...ceInfo.cs => IAnimatedVisualSourceInfo.cs} | 64 +++---- .../CodeGen/InstantiatorGeneratorBase.cs | 163 +++++++----------- .../UIData/CodeGen/LoadedImageSurfaceInfo.cs | 50 ++++++ source/UIData/UIData.projitems | 5 +- tests/CompileDirectory.cmd | 17 ++ tests/CompileDirectory.rsp | 148 ++++++++++++++++ tests/Mocks.cs | 78 +++++++++ 11 files changed, 565 insertions(+), 238 deletions(-) delete mode 100644 source/UIData/CodeGen/AnimatedVisualInfo.cs create mode 100644 source/UIData/CodeGen/IAnimatedVisualInfo.cs rename source/UIData/CodeGen/{AnimatedVisualSourceInfo.cs => IAnimatedVisualSourceInfo.cs} (50%) create mode 100644 source/UIData/CodeGen/LoadedImageSurfaceInfo.cs create mode 100644 tests/CompileDirectory.cmd create mode 100644 tests/CompileDirectory.rsp create mode 100644 tests/Mocks.cs diff --git a/source/UIData/CodeGen/AnimatedVisualInfo.cs b/source/UIData/CodeGen/AnimatedVisualInfo.cs deleted file mode 100644 index ed4652a..0000000 --- a/source/UIData/CodeGen/AnimatedVisualInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections; -using System.Collections.Generic; -using static Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen.InstantiatorGeneratorBase; - -namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen -{ - /// - /// Holds information about code being generated for an IAnimatedVisual. - /// - public sealed class AnimatedVisualInfo - { - internal AnimatedVisualInfo( - AnimatedVisualSourceInfo animatedVisualSourceInfo, - string className, - IReadOnlyList loadedImageSurfaceNodes) - { - AnimatedVisualSourceInfo = animatedVisualSourceInfo; - ClassName = className; - LoadedImageSurfaceNodes = loadedImageSurfaceNodes; - } - - /// - /// The describing the IAnimatedVisualSource that - /// will source the IAnimatedVisual described by this object. - /// - public AnimatedVisualSourceInfo AnimatedVisualSourceInfo { get; } - - /// - /// Gets the name of the IAnimatedVisual class that will be exposed to users. - /// - public string ClassName { get; } - - /// - /// Gets a value indicating whether the AnimatedVisual has LoadedImageSurface. - /// - public bool HasLoadedImageSurface => LoadedImageSurfaceNodes.Count > 0; - - /// - /// Gets the LoadedImageSurface nodes of the AnimatedVisual. - /// - internal IReadOnlyList LoadedImageSurfaceNodes { get; } - } -} diff --git a/source/UIData/CodeGen/CSharpInstantiatorGenerator.cs b/source/UIData/CodeGen/CSharpInstantiatorGenerator.cs index 804ed75..c5d0806 100644 --- a/source/UIData/CodeGen/CSharpInstantiatorGenerator.cs +++ b/source/UIData/CodeGen/CSharpInstantiatorGenerator.cs @@ -71,7 +71,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen /// // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). - protected override void WriteFileStart(CodeBuilder builder, AnimatedVisualSourceInfo info) + protected override void WriteFileStart(CodeBuilder builder, IAnimatedVisualSourceInfo info) { // A sorted set to hold the namespaces that the generated code will use. The set is maintained in sorted order. var namepaces = new SortedSet(); @@ -133,7 +133,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen /// /// Write a class that implements the IAnimatedVisualSource interface. /// - void WriteIAnimatedVisualSource(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteIAnimatedVisualSource(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); @@ -144,19 +144,29 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("diagnostics = null;"); - builder.WriteLine("if (!IsRuntimeCompatible())"); - builder.OpenScope(); + builder.WriteLine(); + + // Check the runtime version and instantiate the highest compatible IAnimatedVisual class. + var animatedVisualInfos = info.AnimatedVisualInfos.OrderByDescending(avi => avi.RequiredUapVersion).ToArray(); + for (var i = 0; i < animatedVisualInfos.Length; i++) + { + var current = animatedVisualInfos[i]; + builder.WriteLine($"if ({current.ClassName}.IsRuntimeCompatible())"); + builder.OpenScope(); + builder.WriteLine($"return new {current.ClassName}(compositor);"); + builder.CloseScope(); + builder.WriteLine(); + } + builder.WriteLine("return null;"); builder.CloseScope(); - builder.WriteLine("return new AnimatedVisual(compositor);"); - builder.CloseScope(); builder.WriteLine(); } /// /// Write a class that implements the IDynamicAnimatedVisualSource interface. /// - void WriteIDynamicAnimatedVisualSource(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteIDynamicAnimatedVisualSource(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); @@ -215,9 +225,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("_isTryCreateAnimatedVisualCalled = true;"); - builder.WriteLine(); builder.WriteLine("diagnostics = null;"); - builder.WriteLine("if (!IsRuntimeCompatible())"); + builder.WriteLine(); + + // Check whether the runtime will support the lowest UAP version required. + var animatedVisualInfos = info.AnimatedVisualInfos.OrderByDescending(avi => avi.RequiredUapVersion).ToArray(); + builder.WriteLine($"if (!{animatedVisualInfos[animatedVisualInfos.Length - 1].ClassName}.IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); @@ -228,14 +241,40 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); - builder.WriteLine("return"); - builder.Indent(); - builder.WriteLine("new AnimatedVisual(compositor,"); - builder.Indent(); - builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => n.FieldName)); - builder.WriteLine(");"); - builder.UnIndent(); - builder.UnIndent(); + builder.WriteLine(); + + // Check the runtime version and instantiate the highest compatible IAnimatedVisual class. + for (var i = 0; i < animatedVisualInfos.Length; i++) + { + var current = animatedVisualInfos[i]; + var versionTestRequired = i < animatedVisualInfos.Length - 1; + + if (i > 0) + { + builder.WriteLine(); + } + + if (versionTestRequired) + { + builder.WriteLine($"if ({current.ClassName}.IsRuntimeCompatible())"); + builder.OpenScope(); + } + + builder.WriteLine("return"); + builder.Indent(); + builder.WriteLine($"new {current.ClassName}("); + builder.Indent(); + builder.WriteLine("compositor,"); + builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => n.FieldName)); + builder.WriteLine(");"); + builder.UnIndent(); + builder.UnIndent(); + if (versionTestRequired) + { + builder.CloseScope(); + } + } + builder.CloseScope(); builder.WriteLine(); @@ -261,7 +300,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } /// - protected override void WriteAnimatedVisualStart(CodeBuilder builder, AnimatedVisualInfo info) + protected override void WriteAnimatedVisualStart(CodeBuilder builder, IAnimatedVisualInfo info) { // Start the instantiator class. builder.WriteLine($"sealed class {info.ClassName} : IAnimatedVisual"); @@ -272,14 +311,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Called by the base class to write the end of the AnimatedVisual class. protected override void WriteAnimatedVisualEnd( CodeBuilder builder, - AnimatedVisualInfo info) + IAnimatedVisualInfo info) { // Write the constructor for the AnimatedVisual class. if (info.HasLoadedImageSurface) { - builder.WriteLine($"internal {info.ClassName}(Compositor compositor,"); + builder.WriteLine($"internal {info.ClassName}("); builder.Indent(); + builder.WriteLine("Compositor compositor,"); + // Define the image surface parameters of the AnimatedVisual() constructor. builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => $"{_s.ReferenceTypeName(n.TypeName)} {_s.CamelCase(n.Name)}")); builder.WriteLine(")"); @@ -298,7 +339,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } else { - builder.WriteLine("internal AnimatedVisual(Compositor compositor)"); + builder.WriteLine($"internal {info.ClassName}(Compositor compositor)"); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.AnimatedVisualSourceInfo.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); @@ -313,6 +354,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine($"TimeSpan IAnimatedVisual.Duration => TimeSpan.FromTicks({info.AnimatedVisualSourceInfo.DurationTicksFieldName});"); builder.WriteLine($"Vector2 IAnimatedVisual.Size => {Vector2(info.AnimatedVisualSourceInfo.CompositionDeclaredSize)};"); builder.WriteLine("void IDisposable.Dispose() => _root?.Dispose();"); + builder.WriteLine(); + + // Write the IsRuntimeCompatible static method. + builder.WriteLine("internal static bool IsRuntimeCompatible()"); + builder.OpenScope(); + builder.WriteLine($"return Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent(\"Windows.Foundation.UniversalApiContract\", {info.RequiredUapVersion});"); + builder.CloseScope(); // Close the scope for the instantiator class. builder.CloseScope(); @@ -322,7 +370,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Called by the base class to write the end of the file (i.e. everything after the body of the AnimatedVisual class). protected override void WriteFileEnd( CodeBuilder builder, - AnimatedVisualSourceInfo info) + IAnimatedVisualSourceInfo info) { // Close the scope for the IAnimatedVisualSource class. builder.CloseScope(); @@ -366,7 +414,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine($"var result = {FieldAssignment(fieldName)}CanvasGeometry.CreateGroup("); builder.Indent(); builder.WriteLine($"null,"); - builder.WriteLine($"new CanvasGeometry[] {{ {string.Join(", ", obj.Geometries.Select(g => CallFactoryFor(g)) ) } }},"); + builder.WriteLine($"new CanvasGeometry[] {{ {string.Join(", ", obj.Geometries.Select(g => CallFactoryFor(g))) } }},"); builder.WriteLine($"{_s.FilledRegionDetermination(obj.FilledRegionDetermination)});"); builder.UnIndent(); } @@ -419,7 +467,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine($"{Float(obj.W)},"); builder.WriteLine($"{Float(obj.H)},"); builder.WriteLine($"{Float(obj.RadiusX)},"); - builder.WriteLine($"{Float(obj.RadiusY)};"); + builder.WriteLine($"{Float(obj.RadiusY)});"); builder.UnIndent(); } @@ -445,7 +493,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine(); } - void WriteEnsureImageLoadingStarted(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteEnsureImageLoadingStarted(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine("void EnsureImageLoadingStarted()"); builder.OpenScope(); diff --git a/source/UIData/CodeGen/CxInstantiatorGenerator.cs b/source/UIData/CodeGen/CxInstantiatorGenerator.cs index b5eb578..b25f473 100644 --- a/source/UIData/CodeGen/CxInstantiatorGenerator.cs +++ b/source/UIData/CodeGen/CxInstantiatorGenerator.cs @@ -93,7 +93,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart( CodeBuilder builder, - AnimatedVisualSourceInfo info) + IAnimatedVisualSourceInfo info) { builder.WriteLine("#include \"pch.h\""); builder.WriteLine($"#include \"{_headerFileName}\""); @@ -188,7 +188,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } /// - protected override void WriteAnimatedVisualStart(CodeBuilder builder, AnimatedVisualInfo info) + protected override void WriteAnimatedVisualStart( + CodeBuilder builder, + IAnimatedVisualInfo info) { // Start writing the instantiator. builder.WriteLine($"ref class {info.ClassName} sealed : public Microsoft::UI::Xaml::Controls::IAnimatedVisual"); @@ -206,7 +208,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Called by the base class to write the end of the AnimatedVisual class. protected override void WriteAnimatedVisualEnd( CodeBuilder builder, - AnimatedVisualInfo info) + IAnimatedVisualInfo info) { if (info.AnimatedVisualSourceInfo.UsesCanvasEffects || info.AnimatedVisualSourceInfo.UsesCanvasGeometry) @@ -237,9 +239,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen if (info.AnimatedVisualSourceInfo.HasLoadedImageSurface) { - builder.WriteLine($"{info.ClassName}(Compositor^ compositor,"); + builder.WriteLine($"{info.ClassName}("); builder.Indent(); - + builder.WriteLine("Compositor^ compositor,"); builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => $"{_s.ReferenceTypeName(n.TypeName)} {_s.CamelCase(n.Name)}")); // Initializer list. @@ -289,7 +291,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine(); builder.WriteLine("property TimeSpan Duration"); builder.OpenScope(); - builder.WriteLine("virtual TimeSpan get() { return { c_durationTicks }; }"); + builder.WriteLine($"virtual TimeSpan get() {{ return {{ {info.AnimatedVisualSourceInfo.DurationTicksFieldName} }}; }}"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property Visual^ RootVisual"); @@ -303,6 +305,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.CloseScope(); builder.WriteLine(); + // Write the IsRuntimeCompatible static method. + builder.WriteLine("static bool IsRuntimeCompatible()"); + builder.OpenScope(); + builder.WriteLine($"return Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(\"Windows.Foundation.UniversalApiContract\", {info.RequiredUapVersion});"); + builder.CloseScope(); + // Close the scope for the instantiator class. builder.UnIndent(); builder.WriteLine("};"); @@ -312,7 +320,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Called by the base class to write the end of the file (i.e. everything after the body of the AnimatedVisual class). protected override void WriteFileEnd( CodeBuilder builder, - AnimatedVisualSourceInfo info) + IAnimatedVisualSourceInfo info) { // Close the anonymous namespace. builder.WriteLine("} // end namespace"); @@ -333,12 +341,23 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen else { builder.WriteLine("diagnostics = nullptr;"); - builder.WriteLine("if (!IsRuntimeCompatible())"); - builder.OpenScope(); + + // Check whether the runtime will support the lowest UAP version required. + var animatedVisualInfos = info.AnimatedVisualInfos.OrderByDescending(avi => avi.RequiredUapVersion).ToArray(); + + // Check the runtime version and instantiate the highest compatible IAnimatedVisual class. + for (var i = 0; i < animatedVisualInfos.Length; i++) + { + var current = animatedVisualInfos[i]; + builder.WriteLine($"if ({current.ClassName}::IsRuntimeCompatible())"); + builder.OpenScope(); + builder.WriteLine("return ref new {current.ClassName}(compositor);"); + builder.CloseScope(); + } + + builder.WriteLine(); builder.WriteLine("return nullptr;"); builder.CloseScope(); - builder.WriteLine("return ref new AnimatedVisual(compositor);"); - builder.CloseScope(); } if (info.HasLoadedImageSurface) @@ -490,12 +509,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen /// /// Generate the body of the TryCreateAnimatedVisual() method for the composition that contains LoadedImageSurfaces. /// - void WriteTryCreateInstantiatorWithImageLoading(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteTryCreateInstantiatorWithImageLoading(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine("m_isTryCreateAnimatedVisualCalled = true;"); - builder.WriteLine(); builder.WriteLine("diagnostics = nullptr;"); - builder.WriteLine("if (!IsRuntimeCompatible())"); + builder.WriteLine(); + + // Check whether the runtime will support the lowest UAP version required. + var animatedVisualInfos = info.AnimatedVisualInfos.OrderByDescending(avi => avi.RequiredUapVersion).ToArray(); + builder.WriteLine($"if (!{animatedVisualInfos[animatedVisualInfos.Length - 1].ClassName}::IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); @@ -506,16 +528,40 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); - builder.WriteLine("return ref new AnimatedVisual(compositor,"); - builder.Indent(); - builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => MakeFieldName(n.Name))); - builder.UnIndent(); - builder.WriteLine(");"); + + // Check the runtime version and instantiate the highest compatible IAnimatedVisual class. + for (var i = 0; i < animatedVisualInfos.Length; i++) + { + var current = animatedVisualInfos[i]; + var versionTestRequired = i < animatedVisualInfos.Length - 1; + + builder.WriteLine(); + if (versionTestRequired) + { + builder.WriteLine($"if ({current.ClassName}::IsRuntimeCompatible())"); + builder.OpenScope(); + } + + builder.WriteLine("return"); + builder.Indent(); + builder.WriteLine($"ref new {current.ClassName}("); + builder.Indent(); + builder.WriteLine("compositor,"); + builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => n.FieldName)); + builder.WriteLine(");"); + builder.UnIndent(); + builder.UnIndent(); + if (versionTestRequired) + { + builder.CloseScope(); + } + } + builder.CloseScope(); builder.WriteLine(); } - void WriteIsAnimatedVisualSourceDynamicGetSet(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteIsAnimatedVisualSourceDynamicGetSet(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine($"bool AnimatedVisuals::{info.ClassName}::IsAnimatedVisualSourceDynamic::get()"); builder.OpenScope(); @@ -532,7 +578,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.CloseScope(); } - void WriteEnsureImageLoadingStarted(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteEnsureImageLoadingStarted(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::EnsureImageLoadingStarted()"); builder.OpenScope(); @@ -573,7 +619,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.WriteLine(); } - void WriteHandleLoadCompleted(CodeBuilder builder, AnimatedVisualSourceInfo info) + void WriteHandleLoadCompleted(CodeBuilder builder, IAnimatedVisualSourceInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::HandleLoadCompleted(LoadedImageSurface^ sender, LoadedImageSourceLoadCompletedEventArgs^ e)"); builder.OpenScope(); diff --git a/source/UIData/CodeGen/IAnimatedVisualInfo.cs b/source/UIData/CodeGen/IAnimatedVisualInfo.cs new file mode 100644 index 0000000..6a2b4ce --- /dev/null +++ b/source/UIData/CodeGen/IAnimatedVisualInfo.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen +{ + /// + /// Holds information about code being generated for an IAnimatedVisual. + /// +#if PUBLIC_UIData + public +#endif + interface IAnimatedVisualInfo + { + /// + /// The describing the IAnimatedVisualSource that + /// will source the IAnimatedVisual described by this object. + /// + IAnimatedVisualSourceInfo AnimatedVisualSourceInfo { get; } + + /// + /// Gets the name of the IAnimatedVisual class that will be exposed to users. + /// + string ClassName { get; } + + /// + /// Gets a value indicating whether the AnimatedVisual has LoadedImageSurface. + /// + bool HasLoadedImageSurface { get; } + + /// + /// The UAP version required by the IAnimatedVisual. + /// + uint RequiredUapVersion { get; } + + /// + /// Gets the XAML LoadedImageSurface nodes of the AnimatedVisual. + /// + IReadOnlyList LoadedImageSurfaceNodes { get; } + } +} diff --git a/source/UIData/CodeGen/AnimatedVisualSourceInfo.cs b/source/UIData/CodeGen/IAnimatedVisualSourceInfo.cs similarity index 50% rename from source/UIData/CodeGen/AnimatedVisualSourceInfo.cs rename to source/UIData/CodeGen/IAnimatedVisualSourceInfo.cs index 6b211d3..70ed270 100644 --- a/source/UIData/CodeGen/AnimatedVisualSourceInfo.cs +++ b/source/UIData/CodeGen/IAnimatedVisualSourceInfo.cs @@ -4,99 +4,81 @@ using System.Collections.Generic; using System.Numerics; -using static Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen.InstantiatorGeneratorBase; namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen { /// /// Holds information about code being generated for an IAnimatedVisualSource. /// - public sealed class AnimatedVisualSourceInfo +#if PUBLIC_UIData + public +#endif + interface IAnimatedVisualSourceInfo { - internal AnimatedVisualSourceInfo( - string className, - string reusableExpressionAnimationFieldName, - string durationTicksFieldName, - Vector2 compositionDeclaredSize, - bool usesCanvas, - bool usesCanvasEffects, - bool usesCanvasGeometry, - bool usesNamespaceWindowsUIXamlMedia, - bool usesStreams, - bool usesCompositeEffect, - IReadOnlyList loadedImageSurfaceNodes) - { - ClassName = className; - ReusableExpressionAnimationFieldName = reusableExpressionAnimationFieldName; - DurationTicksFieldName = durationTicksFieldName; - CompositionDeclaredSize = compositionDeclaredSize; - UsesCanvas = usesCanvas; - UsesCanvasEffects = usesCanvasEffects; - UsesCanvasGeometry = usesCanvasGeometry; - UsesNamespaceWindowsUIXamlMedia = usesNamespaceWindowsUIXamlMedia; - UsesStreams = usesStreams; - UsesCompositeEffect = usesCompositeEffect; - LoadedImageSurfaceNodes = loadedImageSurfaceNodes; - } - /// /// Gets the name of the IAnimatedVisualSource class that will be exposed to users. /// - public string ClassName { get; } + string ClassName { get; } /// /// Gets the name of the field in the instantiator class that holds the reusable ExpressionAnimation. /// - public string ReusableExpressionAnimationFieldName { get; } + string ReusableExpressionAnimationFieldName { get; } /// /// Gets the constant holding the duration of the composition in ticks. /// - public string DurationTicksFieldName { get; } + string DurationTicksFieldName { get; } /// /// Gets the declared size of the composition. /// - public Vector2 CompositionDeclaredSize { get; } + Vector2 CompositionDeclaredSize { get; } /// /// Gets a value indicating whether the composition depends on the Microsoft.Graphics.Canvas namespace. /// - public bool UsesCanvas { get; } + bool UsesCanvas { get; } /// /// Gets a value indicating whether the composition depends on the Microsoft.Graphics.Canvas.Effects namespace. /// - public bool UsesCanvasEffects { get; } + bool UsesCanvasEffects { get; } /// /// Gets a value indicating whether the composition depends on the Microsoft.Graphics.Canvas.Geometry namespace. /// - public bool UsesCanvasGeometry { get; } + bool UsesCanvasGeometry { get; } /// /// Gets a value indicating whether the composition uses the Windows.UI.Xaml.Media namespace. /// - public bool UsesNamespaceWindowsUIXamlMedia { get; } + bool UsesNamespaceWindowsUIXamlMedia { get; } /// /// Gets a value indicating whether the composition uses streams. /// - public bool UsesStreams { get; } + bool UsesStreams { get; } /// /// Gets a value indicating whether the composition has LoadedImageSurface. /// - public bool HasLoadedImageSurface => LoadedImageSurfaceNodes.Count > 0; + bool HasLoadedImageSurface { get; } /// - /// Gets the LoadedImageSurface nodes of the composition. + /// Gets the objects that describe each IAnimatedVisual + /// class that can be returned from the generated code. /// - internal IReadOnlyList LoadedImageSurfaceNodes { get; } + IReadOnlyList AnimatedVisualInfos { get; } /// /// Gets a value indicating whether the composition depends on a composite effect. /// - public bool UsesCompositeEffect { get; } + bool UsesCompositeEffect { get; } + + /// + /// Gets the XAML LoadedImageSurface nodes of the composition. + /// + IReadOnlyList LoadedImageSurfaceNodes { get; } } } diff --git a/source/UIData/CodeGen/InstantiatorGeneratorBase.cs b/source/UIData/CodeGen/InstantiatorGeneratorBase.cs index fe40663..34b76c3 100644 --- a/source/UIData/CodeGen/InstantiatorGeneratorBase.cs +++ b/source/UIData/CodeGen/InstantiatorGeneratorBase.cs @@ -20,7 +20,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen #if PUBLIC_UIData public #endif - abstract class InstantiatorGeneratorBase + abstract class InstantiatorGeneratorBase : IAnimatedVisualSourceInfo { // The name of the field holding the singleton reusable ExpressionAnimation. const string SingletonExpressionAnimationName = "_reusableExpressionAnimation"; @@ -164,28 +164,28 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen /// protected abstract void WriteFileStart( CodeBuilder builder, - AnimatedVisualSourceInfo info); + IAnimatedVisualSourceInfo info); /// /// Writes the start of the IAnimatedVisual implementation class. /// protected abstract void WriteAnimatedVisualStart( CodeBuilder builder, - AnimatedVisualInfo info); + IAnimatedVisualInfo info); /// /// Writes the end of the IAnimatedVisual implementation class. /// protected abstract void WriteAnimatedVisualEnd( CodeBuilder builder, - AnimatedVisualInfo info); + IAnimatedVisualInfo info); /// /// Writes the end of the file. /// protected abstract void WriteFileEnd( CodeBuilder builder, - AnimatedVisualSourceInfo info); + IAnimatedVisualSourceInfo info); /// /// Writes CanvasGeometery.Combination factory code. @@ -309,21 +309,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen { var builder = new CodeBuilder(); - // This object contains information about the AnimatedVisualSourceInfo for use during codegen. - var animatedVisualSourceInfo = new AnimatedVisualSourceInfo( - className: _className, - reusableExpressionAnimationFieldName: SingletonExpressionAnimationName, - durationTicksFieldName: DurationTicksFieldName, - compositionDeclaredSize: _compositionDeclaredSize, - usesCanvas: _animatedVisualGenerators.Any(f => f.UsesCanvas), - usesCanvasEffects: _animatedVisualGenerators.Any(f => f.UsesCanvasEffects), - usesCanvasGeometry: _animatedVisualGenerators.Any(f => f.UsesCanvasGeometry), - usesNamespaceWindowsUIXamlMedia: _animatedVisualGenerators.Any(f => f.UsesNamespaceWindowsUIXamlMedia), - usesStreams: _animatedVisualGenerators.Any(f => f.UsesStreams), - loadedImageSurfaceNodes: GetLoadedImageSurfaceInfos(), - usesCompositeEffect: _animatedVisualGenerators.Any(f => f.UsesCompositeEffect) - ); - // Write the auto-generated warning comment. foreach (var line in AutoGeneratedHeaderText) { @@ -331,7 +316,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } // Write the start of the file. This is everything up to the start of the AnimatedVisual class. - WriteFileStart(builder, animatedVisualSourceInfo); + WriteFileStart(builder, this); // Write the LoadedImageSurface byte arrays into the outer (IAnimatedVisualSource) class. { @@ -356,45 +341,22 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } } - var requiredUapVersion = _animatedVisualGenerators.Select(f => f.RequiredUapVersion).Max(); - - // Write the IsRuntimeCompatible() method. - builder.WriteLine("static bool IsRuntimeCompatible()"); - builder.OpenScope(); -#if false - // TODO This is the implementation for the new UAP contract way of checking versions. It will replace the IsRuntimeCompatible method shortly. - //builder.WriteLine($"return Windows{ScopeResolve}Foundation{ScopeResolve}Metadata{ScopeResolve}ApiInformation{ScopeResolve}IsApiContractPresent(\"Windows.Foundation.UniversalApiContract\", {requiredUapVersion});"); - //builder.CloseScope(); -#endif - builder.WriteLine($"if (!Windows{_stringifier.ScopeResolve}Foundation{_stringifier.ScopeResolve}Metadata{_stringifier.ScopeResolve}ApiInformation{_stringifier.ScopeResolve}IsTypePresent(\"Windows.UI.Composition.CompositionGeometricClip\"))"); - builder.OpenScope(); - builder.WriteLine("return false;"); - builder.CloseScope(); - - if (requiredUapVersion > 7) - { - builder.WriteLine($"if (!Windows{_stringifier.ScopeResolve}Foundation{_stringifier.ScopeResolve}Metadata{_stringifier.ScopeResolve}ApiInformation{_stringifier.ScopeResolve}IsTypePresent(\"Windows.UI.Composition.CompositionVisualSurface\"))"); - builder.OpenScope(); - builder.WriteLine("return false;"); - builder.CloseScope(); - } - - builder.WriteLine("return true;"); - builder.CloseScope(); - builder.WriteLine(); - // Write each AnimatedVisual class. + var firstAnimatedVisualWritten = false; foreach (var animatedVisualGenerator in _animatedVisualGenerators) { - animatedVisualGenerator.WriteAnimatedVisualCode(builder, animatedVisualSourceInfo); + if (firstAnimatedVisualWritten) + { + // Put a blank line between each AnimatedVisual class. + builder.WriteLine(); + } - // TODO - this "break" is just to get compatible output during testing. Remove it to get all the versions. - // TODO - add a WriteLine between each version (i.e. before the second one). - break; + animatedVisualGenerator.WriteAnimatedVisualCode(builder); + firstAnimatedVisualWritten = true; } // Write the end of the file. - WriteFileEnd(builder, animatedVisualSourceInfo); + WriteFileEnd(builder, this); return builder.ToString(); } @@ -488,6 +450,32 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen string ScopeResolve => _stringifier.ScopeResolve; + string IAnimatedVisualSourceInfo.ClassName => _className; + + string IAnimatedVisualSourceInfo.ReusableExpressionAnimationFieldName => SingletonExpressionAnimationName; + + string IAnimatedVisualSourceInfo.DurationTicksFieldName => DurationTicksFieldName; + + Vector2 IAnimatedVisualSourceInfo.CompositionDeclaredSize => _compositionDeclaredSize; + + bool IAnimatedVisualSourceInfo.UsesCanvas => _animatedVisualGenerators.Any(f => f.UsesCanvas); + + bool IAnimatedVisualSourceInfo.UsesCanvasEffects => _animatedVisualGenerators.Any(f => f.UsesCanvasEffects); + + bool IAnimatedVisualSourceInfo.UsesCanvasGeometry => _animatedVisualGenerators.Any(f => f.UsesCanvasGeometry); + + bool IAnimatedVisualSourceInfo.UsesNamespaceWindowsUIXamlMedia => _animatedVisualGenerators.Any(f => f.UsesNamespaceWindowsUIXamlMedia); + + bool IAnimatedVisualSourceInfo.UsesStreams => _animatedVisualGenerators.Any(f => f.UsesStreams); + + IReadOnlyList IAnimatedVisualSourceInfo.AnimatedVisualInfos => _animatedVisualGenerators; + + bool IAnimatedVisualSourceInfo.UsesCompositeEffect => _animatedVisualGenerators.Any(f => f.UsesCompositeEffect); + + bool IAnimatedVisualSourceInfo.HasLoadedImageSurface => GetLoadedImageSurfaceInfos().Any(); + + IReadOnlyList IAnimatedVisualSourceInfo.LoadedImageSurfaceNodes => GetLoadedImageSurfaceInfos(); + static LoadedImageSurfaceInfo LoadedImageSurfaceInfoFromObjectData(ObjectData node) { if (!node.IsLoadedImageSurface) @@ -511,48 +499,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen static IEnumerable OrderByName(IEnumerable nodes) => nodes.OrderBy(n => n.Name, AlphanumericStringComparer.Instance); - /// - /// Describes LoadedImageSurface objects in the composition. - /// - protected internal class LoadedImageSurfaceInfo - { - internal LoadedImageSurfaceInfo( - string typeName, - string name, - string fieldName, - string bytesFieldName, - Uri imageUri, - Wmd.LoadedImageSurface.LoadedImageSurfaceType loadedImageSurfaceType, - byte[] bytes) - { - TypeName = typeName; - Name = name; - FieldName = fieldName; - BytesFieldName = bytesFieldName; - ImageUri = imageUri; - LoadedImageSurfaceType = loadedImageSurfaceType; - Bytes = bytes; - } - - public string TypeName { get; } - - public string Name { get; } - - public string FieldName { get; } - - public string BytesFieldName { get; } - - public Uri ImageUri { get; } - - public Wmd.LoadedImageSurface.LoadedImageSurfaceType LoadedImageSurfaceType { get; } - - public byte[] Bytes { get; } - } - /// /// Generates an IAnimatedVisual implementation. /// - sealed class AnimatedVisualGenerator + sealed class AnimatedVisualGenerator : IAnimatedVisualInfo { readonly HashSet<(ObjectData, ObjectData)> _factoriesAlreadyCalled = new HashSet<(ObjectData, ObjectData)>(); readonly InstantiatorGeneratorBase _owner; @@ -647,6 +597,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen _rootNode.RequiresStorage = true; } + internal IAnimatedVisualInfo AnimatedVisualInfo => this; + // Returns the nodes that can be shared between multiple IAnimatedVisuals. internal IEnumerable GetShareableNodes() => _nodes.Where(n => n.IsShareableNode); @@ -686,6 +638,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen internal bool UsesCompositeEffect => _nodes.Where(n => n.UsesCompositeEffect).Any(); + string ScopeResolve => _stringifier.ScopeResolve; + string Const(string value) => _stringifier.Const(value); string Deref => _stringifier.Deref; @@ -861,18 +815,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen WriteObjectFactoryStartWithoutCache(builder, node, parameters); } - internal void WriteAnimatedVisualCode(CodeBuilder builder, AnimatedVisualSourceInfo animatedVisualSourceInfo) + internal void WriteAnimatedVisualCode(CodeBuilder builder) { _owner._currentAnimatedVisualGenerator = this; - var animatedVisualInfo = new AnimatedVisualInfo( - animatedVisualSourceInfo, - className: "AnimatedVisual", - loadedImageSurfaceNodes: GetLoadedImageSurfaceInfos().ToArray()); // Write the body of the AnimatedVisual class. - _owner.WriteAnimatedVisualStart(builder, animatedVisualInfo); + _owner.WriteAnimatedVisualStart(builder, this); // Write fields for constant values. + builder.WriteComment($"Animation duration: {_owner._compositionDuration.Ticks / (double)System.TimeSpan.TicksPerSecond,-1:N3} seconds."); WriteField(builder, Const(_stringifier.Int64TypeName), $"{DurationTicksFieldName} = {_stringifier.Int64(_owner._compositionDuration.Ticks)}"); // Write fields for each object that needs storage (i.e. objects that are @@ -888,11 +839,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen // Write methods for each node. foreach (var node in _nodes) { - WriteCodeForNode(builder, animatedVisualSourceInfo, node); + WriteCodeForNode(builder, node); } // Write the end of the AnimatedVisual class. - _owner.WriteAnimatedVisualEnd(builder, animatedVisualInfo); + _owner.WriteAnimatedVisualEnd(builder, this); _owner._currentAnimatedVisualGenerator = null; } @@ -913,7 +864,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen } // Generates code for the given node. The code is written into the given CodeBuilder. - void WriteCodeForNode(CodeBuilder builder, AnimatedVisualSourceInfo info, ObjectData node) + void WriteCodeForNode(CodeBuilder builder, ObjectData node) { // Only generate if the node is not inlined into the caller. if (!node.Inlined) @@ -2048,6 +1999,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen builder.CloseScope(); builder.WriteLine(); } + + IAnimatedVisualSourceInfo IAnimatedVisualInfo.AnimatedVisualSourceInfo => _owner; + + string IAnimatedVisualInfo.ClassName => $"AnimatedVisual_UAPv{_requiredUapVersion}"; + + bool IAnimatedVisualInfo.HasLoadedImageSurface => GetLoadedImageSurfaceInfos().Any(); + + IReadOnlyList IAnimatedVisualInfo.LoadedImageSurfaceNodes => GetLoadedImageSurfaceInfos().ToArray(); + + uint IAnimatedVisualInfo.RequiredUapVersion => _requiredUapVersion; } // Aggregates ObjectData nodes that are shared between different IAnimatedVisual instances, diff --git a/source/UIData/CodeGen/LoadedImageSurfaceInfo.cs b/source/UIData/CodeGen/LoadedImageSurfaceInfo.cs new file mode 100644 index 0000000..0339d24 --- /dev/null +++ b/source/UIData/CodeGen/LoadedImageSurfaceInfo.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Wmd = Microsoft.Toolkit.Uwp.UI.Lottie.WinUIXamlMediaData; + +namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen +{ + /// + /// Describes LoadedImageSurface objects in the composition. + /// +#if PUBLIC_UIData + public +#endif + sealed class LoadedImageSurfaceInfo + { + internal LoadedImageSurfaceInfo( + string typeName, + string name, + string fieldName, + string bytesFieldName, + Uri imageUri, + Wmd.LoadedImageSurface.LoadedImageSurfaceType loadedImageSurfaceType, + byte[] bytes) + { + TypeName = typeName; + Name = name; + FieldName = fieldName; + BytesFieldName = bytesFieldName; + ImageUri = imageUri; + LoadedImageSurfaceType = loadedImageSurfaceType; + Bytes = bytes; + } + + public string TypeName { get; } + + public string Name { get; } + + public string FieldName { get; } + + public string BytesFieldName { get; } + + public Uri ImageUri { get; } + + public Wmd.LoadedImageSurface.LoadedImageSurfaceType LoadedImageSurfaceType { get; } + + public byte[] Bytes { get; } + } +} diff --git a/source/UIData/UIData.projitems b/source/UIData/UIData.projitems index 47d86ad..9c3f7cf 100644 --- a/source/UIData/UIData.projitems +++ b/source/UIData/UIData.projitems @@ -7,15 +7,16 @@ - - + + + diff --git a/tests/CompileDirectory.cmd b/tests/CompileDirectory.cmd new file mode 100644 index 0000000..def7765 --- /dev/null +++ b/tests/CompileDirectory.cmd @@ -0,0 +1,17 @@ +@echo off +setlocal +if '%1' EQU '' ( + echo No directory provided. + goto :eof +) + +echo Compiling all .cs files under %1 + +:: The C# compiler on your machine. +set cscPath="%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Roslyn\csc.exe" + +:: WinUI local copy. Needed because we can't mock IDynamicAnimatedVisualSource in C# due to the use of WinRT events. +set winuiWinmdPath="%homedrive%%homepath%\.nuget\packages\microsoft.ui.xaml\2.2.190917002\lib\uap10.0\Microsoft.UI.Xaml.winmd" + +for /r "%1" %%F in (*.cs) do @%cscPath% /noconfig @CompileDirectory.rsp /reference:%winuiWinmdPath% "%%F" /out:"%%~dpnF.dll" & del "%%~dpnF.dll" + diff --git a/tests/CompileDirectory.rsp b/tests/CompileDirectory.rsp new file mode 100644 index 0000000..1368c8d --- /dev/null +++ b/tests/CompileDirectory.rsp @@ -0,0 +1,148 @@ +# Do not show the csc signon. +/nologo +# Do not emit PDB +/debug- +/nowarn:2008,1701,1702,2008 +/nostdlib+ +/platform:x86 +/errorreport:prompt +/warn:0 +/define:DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS +/errorendlocation +/preferreduilang:en-US +/highentropyva+ +/lib:"C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\microsoft.netcore.universalwindowsplatform\6.2.9\ref\uap10.0.15138" +/reference:"Microsoft.CSharp.dll" +/reference:"C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\XamlCompiler\Microsoft.UI.Xaml.Markup.winmd" +/reference:"Microsoft.VisualBasic.dll" +/reference:"Microsoft.Win32.Primitives.dll" +/reference:"mscorlib.dll" +/reference:"netstandard.dll" +/reference:"System.AppContext.dll" +/reference:"System.Buffers.dll" +/reference:"System.Collections.Concurrent.dll" +/reference:"System.Collections.dll" +/reference:"System.Collections.Immutable.dll" +/reference:"System.Collections.NonGeneric.dll" +/reference:"System.Collections.Specialized.dll" +/reference:"System.ComponentModel.Annotations.dll" +/reference:"System.ComponentModel.Composition.dll" +/reference:"System.ComponentModel.DataAnnotations.dll" +/reference:"System.ComponentModel.dll" +/reference:"System.ComponentModel.EventBasedAsync.dll" +/reference:"System.ComponentModel.Primitives.dll" +/reference:"System.ComponentModel.TypeConverter.dll" +/reference:"System.Configuration.dll" +/reference:"System.Core.dll" +/reference:"System.Data.Common.dll" +/reference:"System.Data.dll" +/reference:"System.Diagnostics.Contracts.dll" +/reference:"System.Diagnostics.Debug.dll" +/reference:"System.Diagnostics.FileVersionInfo.dll" +/reference:"System.Diagnostics.Process.dll" +/reference:"System.Diagnostics.StackTrace.dll" +/reference:"System.Diagnostics.TextWriterTraceListener.dll" +/reference:"System.Diagnostics.Tools.dll" +/reference:"System.Diagnostics.TraceSource.dll" +/reference:"System.Diagnostics.Tracing.dll" +/reference:"System.dll" +/reference:"System.Drawing.dll" +/reference:"System.Drawing.Primitives.dll" +/reference:"System.Dynamic.Runtime.dll" +/reference:"System.Globalization.Calendars.dll" +/reference:"System.Globalization.dll" +/reference:"System.Globalization.Extensions.dll" +/reference:"System.IO.dll" +/reference:"System.IO.IsolatedStorage.dll" +/reference:"System.IO.MemoryMappedFiles.dll" +/reference:"System.IO.Pipes.dll" +/reference:"System.IO.Ports.dll" +/reference:"System.IO.UnmanagedMemoryStream.dll" +/reference:"System.Linq.dll" +/reference:"System.Linq.Expressions.dll" +/reference:"System.Linq.Parallel.dll" +/reference:"System.Linq.Queryable.dll" +/reference:"System.Net.dll" +/reference:"System.Net.NameResolution.dll" +/reference:"System.Net.NetworkInformation.dll" +/reference:"System.Net.Primitives.dll" +/reference:"System.Net.Requests.dll" +/reference:"System.Net.Security.dll" +/reference:"System.Numerics.dll" +/reference:"System.Numerics.Vectors.dll" +/reference:"System.Numerics.Vectors.WindowsRuntime.dll" +/reference:"System.ObjectModel.dll" +/reference:"System.Reflection.Context.dll" +/reference:"System.Reflection.DispatchProxy.dll" +/reference:"System.Reflection.dll" +/reference:"System.Reflection.Extensions.dll" +/reference:"System.Reflection.Metadata.dll" +/reference:"System.Reflection.Primitives.dll" +/reference:"System.Reflection.TypeExtensions.dll" +/reference:"System.Resources.Reader.dll" +/reference:"System.Resources.ResourceManager.dll" +/reference:"System.Resources.Writer.dll" +/reference:"System.Runtime.CompilerServices.VisualC.dll" +/reference:"System.Runtime.dll" +/reference:"System.Runtime.Extensions.dll" +/reference:"System.Runtime.Handles.dll" +/reference:"System.Runtime.InteropServices.dll" +/reference:"System.Runtime.InteropServices.RuntimeInformation.dll" +/reference:"System.Runtime.InteropServices.WindowsRuntime.dll" +/reference:"System.Runtime.Numerics.dll" +/reference:"System.Runtime.Serialization.dll" +/reference:"System.Runtime.Serialization.Formatters.dll" +/reference:"System.Runtime.Serialization.Json.dll" +/reference:"System.Runtime.Serialization.Primitives.dll" +/reference:"System.Runtime.Serialization.Xml.dll" +/reference:"System.Runtime.WindowsRuntime.dll" +/reference:"System.Runtime.WindowsRuntime.UI.Xaml.dll" +/reference:"System.Security.AccessControl.dll" +/reference:"System.Security.Claims.dll" +/reference:"System.Security.Cryptography.Algorithms.dll" +/reference:"System.Security.Cryptography.Cng.dll" +/reference:"System.Security.Cryptography.Csp.dll" +/reference:"System.Security.Cryptography.Encoding.dll" +/reference:"System.Security.Cryptography.Primitives.dll" +/reference:"System.Security.Cryptography.X509Certificates.dll" +/reference:"System.Security.dll" +/reference:"System.Security.Principal.dll" +/reference:"System.Security.Principal.Windows.dll" +/reference:"System.Security.SecureString.dll" +/reference:"System.ServiceModel.dll" +/reference:"System.ServiceModel.Duplex.dll" +/reference:"System.ServiceModel.Http.dll" +/reference:"System.ServiceModel.NetTcp.dll" +/reference:"System.ServiceModel.Primitives.dll" +/reference:"System.ServiceModel.Security.dll" +/reference:"System.ServiceModel.Web.dll" +/reference:"System.ServiceProcess.dll" +/reference:"System.Text.Encoding.CodePages.dll" +/reference:"System.Text.Encoding.dll" +/reference:"System.Text.Encoding.Extensions.dll" +/reference:"System.Text.RegularExpressions.dll" +/reference:"System.Threading.dll" +/reference:"System.Threading.Overlapped.dll" +/reference:"System.Threading.Tasks.Dataflow.dll" +/reference:"System.Threading.Tasks.dll" +/reference:"System.Threading.Tasks.Parallel.dll" +/reference:"System.Threading.Thread.dll" +/reference:"System.Threading.ThreadPool.dll" +/reference:"System.Threading.Timer.dll" +/reference:"System.Transactions.dll" +/reference:"System.Transactions.Local.dll" +/reference:"System.ValueTuple.dll" +/reference:"System.Web.dll" +/reference:"System.Web.HttpUtility.dll" +/reference:"System.Windows.dll" +/reference:"WindowsBase.dll" +/reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" +/reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd" +/reference:"C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Facade\Windows.winmd" +/ruleset:"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Team Tools\Static Analysis Tools\\Rule Sets\MinimumRecommendedRules.ruleset" +/subsystemversion:6.02 +/target:library +/utf8output +/langversion:7.3 +Mocks.cs + diff --git a/tests/Mocks.cs b/tests/Mocks.cs new file mode 100644 index 0000000..d3d3161 --- /dev/null +++ b/tests/Mocks.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file contains mocks of Win2D for use when testing that LottieGen's output is compilable. +using System; +using System.Collections.Generic; +using System.Numerics; +using Windows.Foundation; +using Windows.Foundation.Metadata; +using Windows.Graphics; +using Windows.Graphics.Effects; +using Windows.UI.Composition; + +namespace Microsoft.Graphics.Canvas +{ + enum CanvasComposite + { + DestinationIn, + DestinationOut, + } +} + +namespace Microsoft.Graphics.Canvas.Effects +{ + class CompositeEffect : Windows.Graphics.Effects.IGraphicsEffect + { + public CanvasComposite Mode { get; set; } + public string Name { get; set; } + public IList Sources { get; } + } +} + +namespace Microsoft.Graphics.Canvas.Geometry +{ + enum CanvasFigureLoop + { + Open, + Closed, + } + + enum CanvasFilledRegionDetermination + { + Winding, + Alternate, + } + + enum CanvasGeometryCombine + { + Intersect, + Xor, + Exclude, + Union, + } + + class CanvasGeometry : IGeometrySource2D + { + public static CanvasGeometry CreateEllipse(object arg0, float arg1, float arg2, float arg3, float arg4) => null; + public static CanvasGeometry CreateGroup(object arg0, CanvasGeometry[] arg1) => null; + public static CanvasGeometry CreateGroup(object arg0, CanvasGeometry[] arg1, CanvasFilledRegionDetermination arg3) => null; + public static CanvasGeometry CreatePath(CanvasPathBuilder builder) => null; + public static CanvasGeometry CreateRoundedRectangle(object arg0, float arg1, float arg2, float arg3, float arg4, float arg5, float arg6) => null; + public CanvasGeometry CombineWith(CanvasGeometry arg) => null; + public CanvasGeometry CombineWith(CanvasGeometry otherGeometry, Matrix3x2 otherGeometryTransform, CanvasGeometryCombine combine) => null; + public CanvasGeometry Transform(Matrix3x2 transform) => null; + } + + class CanvasPathBuilder : IDisposable + { + public CanvasPathBuilder(object device) { } + public void AddCubicBezier(Vector2 arg0, Vector2 arg1, Vector2 arg2) { } + public void AddLine(Vector2 value) { } + public void BeginFigure(Vector2 arg) { } + public void EndFigure(CanvasFigureLoop arg) { } + public void SetFilledRegionDetermination(CanvasFilledRegionDetermination arg) { } + void IDisposable.Dispose() => throw new NotImplementedException(); + } +}