Update NuGets, optimize allocations.
Switch to newest JSON parser. Optimize allocations by using ReadOnlySpan<T> in places where we previously use IEnumerable<T> as a way of protecting arrays for modification.
This commit is contained in:
Родитель
6eacb93a64
Коммит
b014855ed7
|
@ -37,11 +37,13 @@
|
|||
<SubType>Designer</SubType>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>11.0.2</Version>
|
||||
<Version>12.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Memory" Version="4.5.1" />
|
||||
<PackageReference Include="System.Numerics.Vectors">
|
||||
<Version>4.5.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
|
||||
<PackageReference Include="System.ValueTuple">
|
||||
<Version>4.5.0</Version>
|
||||
</PackageReference>
|
||||
|
|
|
@ -22,13 +22,14 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.1-beta.61">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Memory" Version="4.5.1" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\source\LottieReader\LottieReader.projitems" Label="Shared" />
|
||||
|
|
|
@ -202,7 +202,13 @@
|
|||
<Version>2.1.181025003-prerelease</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>11.0.2</Version>
|
||||
<Version>12.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Memory">
|
||||
<Version>4.5.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe">
|
||||
<Version>4.5.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Win2D.uwp">
|
||||
<Version>1.23.0</Version>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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="8e772a41-9ca3-4339-a6a1-093cb9e19f2d" Publisher="CN=developer" Version="1.0.34.0" />
|
||||
<Identity Name="8e772a41-9ca3-4339-a6a1-093cb9e19f2d" Publisher="CN=yongql" Version="1.0.35.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="8e772a41-9ca3-4339-a6a1-093cb9e19f2d" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Lottie Viewer</DisplayName>
|
||||
|
|
|
@ -8,4 +8,9 @@
|
|||
|
||||
<Import Project="..\..\source\LottieData\LottieData.projitems" Label="Shared" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Memory" Version="4.5.1" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<Import Project="..\..\source\LottieReader\LottieReader.projitems" Label="Shared" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -773,13 +773,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie
|
|||
if (obj.Shapes.Count == 1)
|
||||
{
|
||||
var child = obj.Shapes[0];
|
||||
if (!obj.Animators.Any())
|
||||
if (obj.Animators.Count == 0)
|
||||
{
|
||||
// The container has no animations. It can be replaced with its child as
|
||||
// long as the child doesn't animate any of the non-default properties and
|
||||
// the container isn't referenced by an animation.
|
||||
}
|
||||
else if (!child.Animators.Any() && child.Type == Wd.CompositionObjectType.CompositionContainerShape)
|
||||
else if (child.Animators.Count == 0 && child.Type == Wd.CompositionObjectType.CompositionContainerShape)
|
||||
{
|
||||
// The child has no animations. It can be replaced with its parent as long
|
||||
// as the parent doesn't animate any of the child's non-default properties
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
/// <summary>
|
||||
/// Gets the keyframes that describe how the value should be animated.
|
||||
/// </summary>
|
||||
public IEnumerable<KeyFrame<T>> KeyFrames => _keyFrames;
|
||||
public ReadOnlySpan<KeyFrame<T>> KeyFrames => _keyFrames;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property index used for expressions.
|
||||
|
@ -77,7 +77,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
/// <inheritdoc/>
|
||||
public override string ToString() =>
|
||||
IsAnimated
|
||||
? string.Join(" -> ", KeyFrames.Select(kf => kf.Value.ToString()))
|
||||
? string.Join(" -> ", _keyFrames.Select(kf => kf.Value.ToString()))
|
||||
: InitialValue.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="ReadOnlySpan{T}"/> to make it easier to treat them
|
||||
/// like IEnumerables.
|
||||
/// </summary>
|
||||
#if !WINDOWS_UWP
|
||||
public
|
||||
#endif
|
||||
static class ExtensionMethods
|
||||
{
|
||||
public static bool Any<TSource>(this ReadOnlySpan<TSource> source)
|
||||
{
|
||||
return source.Length > 0;
|
||||
}
|
||||
|
||||
public static bool Any<TSource>(this ReadOnlySpan<TSource> source, Func<TSource, bool> predicate)
|
||||
{
|
||||
for (var i = 0; i < source.Length; i++)
|
||||
{
|
||||
if (predicate(source[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TResult[] SelectToArray<TSource, TResult>(this ReadOnlySpan<TSource> source, Func<TSource, TResult> selector)
|
||||
{
|
||||
var result = new TResult[source.Length];
|
||||
for (var i = 0; i < source.Length; i++)
|
||||
{
|
||||
result[i] = selector(source[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double Max<TSource>(this ReadOnlySpan<TSource> source, Func<TSource, double> selector)
|
||||
{
|
||||
var result = double.NegativeInfinity;
|
||||
|
||||
foreach (var item in source)
|
||||
{
|
||||
var candidate = selector(item);
|
||||
if (candidate > result)
|
||||
{
|
||||
result = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double Min<TSource>(this ReadOnlySpan<TSource> source, Func<TSource, double> selector)
|
||||
{
|
||||
var result = double.PositiveInfinity;
|
||||
|
||||
foreach (var item in source)
|
||||
{
|
||||
var candidate = selector(item);
|
||||
if (candidate < result)
|
||||
{
|
||||
result = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,9 +44,17 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
/// Returns the first gradient stop in a sequence that is a color. Opacity will always be
|
||||
/// set to 1.
|
||||
/// </summary>
|
||||
public static Color GetFirstColor(IEnumerable<GradientStop> gradientStops)
|
||||
public static Color GetFirstColor(ReadOnlySpan<GradientStop> gradientStops)
|
||||
{
|
||||
return gradientStops.Select(stop => stop.Color).FirstOrDefault(color => color != null);
|
||||
foreach (var stop in gradientStops)
|
||||
{
|
||||
if (stop.Color != null)
|
||||
{
|
||||
return stop.Color;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -19,7 +20,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
#endif
|
||||
abstract class Layer : LottieObject
|
||||
{
|
||||
static Mask[] _emptyMasks = new Mask[0];
|
||||
static readonly Mask[] _emptyMasks = new Mask[0];
|
||||
readonly Mask[] _masks;
|
||||
|
||||
protected private Layer(
|
||||
|
@ -96,7 +97,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
/// <summary>
|
||||
/// Gets the list of masks appplied to the layer.
|
||||
/// </summary>
|
||||
public IEnumerable<Mask> Masks => _masks == null ? _emptyMasks : _masks;
|
||||
public ReadOnlySpan<Mask> Masks => _masks;
|
||||
|
||||
public enum LayerType
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)\Animatable.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ExtensionMethods.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)\AnimatableVector3.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)\AnimatableXYZ.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)\Asset.cs" />
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="LottieData.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Optimization
|
|||
|
||||
// If the geometries have different numbers of segments they can't be animated. However
|
||||
// in one specific case we can fix that.
|
||||
var geometries = value.KeyFrames.Select(kf => kf.Value.Items.ToArray()).ToArray();
|
||||
var geometries = value.KeyFrames.SelectToArray(kf => kf.Value.Items.ToArray());
|
||||
var distinctSegmentCounts = geometries.Select(g => g.Length).Distinct().Count();
|
||||
|
||||
if (distinctSegmentCounts != 2)
|
||||
|
@ -106,13 +106,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Optimization
|
|||
}
|
||||
|
||||
// Create a new Animatable<PathGeometry> which has only one segment in each keyframe.
|
||||
var hacked = optimized.KeyFrames.Select(pg => HackPathGeometry(pg));
|
||||
var hacked = optimized.KeyFrames.SelectToArray(pg => HackPathGeometry(pg));
|
||||
return new Animatable<Sequence<BezierSegment>>(hacked.First().Value, hacked, optimized.PropertyIndex);
|
||||
}
|
||||
|
||||
static KeyFrame<Sequence<BezierSegment>> HackPathGeometry(KeyFrame<Sequence<BezierSegment>> value)
|
||||
{
|
||||
return new KeyFrame<Sequence<BezierSegment>>(value.Frame, new Sequence<BezierSegment>(new[] { value.Value.Items.First() }), Vector3.Zero, Vector3.Zero, value.Easing);
|
||||
return new KeyFrame<Sequence<BezierSegment>>(value.Frame, new Sequence<BezierSegment>(new[] { value.Value.Items[0] }), Vector3.Zero, Vector3.Zero, value.Easing);
|
||||
}
|
||||
|
||||
// True iff b is between and c.
|
||||
|
@ -154,8 +154,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Optimization
|
|||
}
|
||||
else
|
||||
{
|
||||
var keyFrames = OptimizeKeyFrames(value.InitialValue, value.KeyFrames).ToArray();
|
||||
if (comparer.Equals(keyFrames, value.KeyFrames))
|
||||
var keyFrames = OptimizeKeyFrames(value.InitialValue, value.KeyFrames.ToArray()).ToArray();
|
||||
if (comparer.Equals(keyFrames, value.KeyFrames.ToArray()))
|
||||
{
|
||||
// Optimization didn't achieve anything.
|
||||
result = value;
|
||||
|
@ -379,7 +379,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Optimization
|
|||
return false;
|
||||
}
|
||||
|
||||
return x.InitialValue.Equals(y.InitialValue) && Equals(x.KeyFrames, y.KeyFrames);
|
||||
return x.InitialValue.Equals(y.InitialValue) && x.KeyFrames.SequenceEqual(y.KeyFrames);
|
||||
}
|
||||
|
||||
public int GetHashCode(KeyFrame<T> obj) => obj.GetHashCode();
|
||||
|
|
|
@ -29,12 +29,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
/// <summary>
|
||||
/// Gets the items in the sequence.
|
||||
/// </summary>
|
||||
public IEnumerable<T> Items => _items;
|
||||
public ReadOnlySpan<T> Items => _items;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Sequence<T> other) =>
|
||||
other != null &&
|
||||
Enumerable.SequenceEqual(_items, other.Items);
|
||||
Enumerable.SequenceEqual(_items, other._items);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj)
|
||||
|
@ -62,6 +62,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"{ItemTypeName}s: {string.Join(", ", Items)}";
|
||||
public override string ToString() => $"{ItemTypeName}s: {string.Join(", ", _items)}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,9 +215,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Tools
|
|||
yield return FromTransform(layer.Transform);
|
||||
if (layer.Masks != null)
|
||||
{
|
||||
foreach (var mask in layer.Masks)
|
||||
for (var i = 0; i < layer.Masks.Length; i++)
|
||||
{
|
||||
yield return FromMask(mask);
|
||||
yield return FromMask(layer.Masks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,9 +296,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Tools
|
|||
yield return item;
|
||||
}
|
||||
|
||||
foreach (var shapeContent in layer.Contents)
|
||||
for (var i = 0; i < layer.Contents.Length; i++)
|
||||
{
|
||||
yield return FromShapeLayerContent(shapeContent);
|
||||
yield return FromShapeLayerContent(layer.Contents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,9 +379,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Tools
|
|||
yield return item;
|
||||
}
|
||||
|
||||
foreach (var item in content.Items)
|
||||
for (var i = 0; i < content.Items.Length; i++)
|
||||
{
|
||||
yield return FromShapeLayerContent(item);
|
||||
yield return FromShapeLayerContent(content.Items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Tools
|
|||
}
|
||||
else
|
||||
{
|
||||
var keyframesString = string.Join(", ", animatable.KeyFrames.Select(kf => $"{FromKeyFrame(kf)}"));
|
||||
var keyframesString = string.Join(", ", animatable.KeyFrames.SelectToArray(kf => $"{FromKeyFrame(kf)}"));
|
||||
|
||||
return new XElement(name, keyframesString);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
||||
{
|
||||
|
@ -11,16 +13,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
#endif
|
||||
sealed class ShapeGroup : ShapeLayerContent
|
||||
{
|
||||
readonly ShapeLayerContent[] _items;
|
||||
|
||||
public ShapeGroup(
|
||||
string name,
|
||||
string matchName,
|
||||
IEnumerable<ShapeLayerContent> items)
|
||||
: base(name, matchName)
|
||||
{
|
||||
Items = items;
|
||||
_items = items.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<ShapeLayerContent> Items { get; }
|
||||
public ReadOnlySpan<ShapeLayerContent> Items => _items;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ShapeContentType ContentType => ShapeContentType.Group;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -12,7 +13,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
#endif
|
||||
sealed class ShapeLayer : Layer
|
||||
{
|
||||
readonly IEnumerable<ShapeLayerContent> _shapes;
|
||||
readonly ShapeLayerContent[] _shapes;
|
||||
|
||||
public ShapeLayer(
|
||||
string name,
|
||||
|
@ -44,10 +45,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
autoOrient,
|
||||
masks)
|
||||
{
|
||||
_shapes = shapes;
|
||||
_shapes = shapes.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<ShapeLayerContent> Contents => _shapes.AsEnumerable();
|
||||
public ReadOnlySpan<ShapeLayerContent> Contents => _shapes;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override LayerType Type => LayerType.Shape;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
||||
{
|
||||
|
@ -11,6 +13,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
#endif
|
||||
sealed class SolidColorStroke : ShapeLayerContent
|
||||
{
|
||||
readonly double[] _dashPattern;
|
||||
|
||||
public SolidColorStroke(
|
||||
string name,
|
||||
string matchName,
|
||||
|
@ -25,7 +29,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
: base(name, matchName)
|
||||
{
|
||||
DashOffset = dashOffset;
|
||||
DashPattern = dashPattern;
|
||||
_dashPattern = dashPattern.ToArray();
|
||||
Color = color;
|
||||
OpacityPercent = opacityPercent;
|
||||
Thickness = thickness;
|
||||
|
@ -40,7 +44,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData
|
|||
|
||||
public Animatable<double> Thickness { get; }
|
||||
|
||||
public IEnumerable<double> DashPattern { get; }
|
||||
public ReadOnlySpan<double> DashPattern => _dashPattern;
|
||||
|
||||
public Animatable<double> DashOffset { get; }
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieData.Tools
|
|||
}
|
||||
}
|
||||
|
||||
_maskCount += layer.Masks.Count();
|
||||
_maskCount += layer.Masks.Length;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
if (layer.Masks != null &&
|
||||
layer.Masks.Any())
|
||||
{
|
||||
Mask mask = layer.Masks.First();
|
||||
var mask = layer.Masks[0];
|
||||
|
||||
if (mask.Inverted)
|
||||
{
|
||||
|
@ -282,7 +282,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
|
||||
// Translation currently does not support having multiple paths for masks.
|
||||
// If possible users should combine masks when exporting to json.
|
||||
if (layer.Masks.Skip(1).Any())
|
||||
if (layer.Masks.Length > 1)
|
||||
{
|
||||
_unsupported.MultipleShapeMasks();
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
mask.Opacity.InitialValue == 100 &&
|
||||
!mask.Opacity.IsAnimated &&
|
||||
mask.Mode == Mask.MaskMode.Additive &&
|
||||
layer.Masks.Count() == 1)
|
||||
layer.Masks.Length == 1)
|
||||
{
|
||||
var geometry = mask.Points;
|
||||
|
||||
|
@ -847,7 +847,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
var bScale = b.InitialValue;
|
||||
return new Animatable<double>(
|
||||
initialValue: a.InitialValue * bScale,
|
||||
keyFrames: a.KeyFrames.Select(kf => new KeyFrame<double>(
|
||||
keyFrames: a.KeyFrames.SelectToArray(kf => new KeyFrame<double>(
|
||||
kf.Frame,
|
||||
kf.Value * (bScale / 100),
|
||||
kf.SpatialControlPoint1,
|
||||
|
@ -1050,7 +1050,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
CompositionShape TranslateShapeLayerContents(
|
||||
TranslationContext context,
|
||||
ShapeContentContext shapeContext,
|
||||
IEnumerable<ShapeLayerContent> contents)
|
||||
ReadOnlySpan<ShapeLayerContent> contents)
|
||||
{
|
||||
// The Contents of a ShapeLayer is a list of instructions for a stack machine.
|
||||
|
||||
|
@ -1066,7 +1066,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
var result = container;
|
||||
|
||||
// If the contents contains a repeater, generate repeated contents
|
||||
if (contents.Where(slc => slc.ContentType == ShapeContentType.Repeater).Any())
|
||||
if (contents.Any(slc => slc.ContentType == ShapeContentType.Repeater))
|
||||
{
|
||||
// The contents contains a repeater. Treat it as if there are n sets of items (where n
|
||||
// equals the Count of the repeater). In each set, replace the repeater with
|
||||
|
@ -1105,7 +1105,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
// by n transforms.
|
||||
// TODO - currently ignoring the StartOpacityPercent and EndOpacityPercent - should generate a new transform
|
||||
// that interpolates that.
|
||||
var generatedItems = itemsBeforeRepeater.Concat(Enumerable.Repeat(repeater.Transform, i + 1)).Concat(itemsAfterRepeater);
|
||||
var generatedItems = itemsBeforeRepeater.Concat(Enumerable.Repeat(repeater.Transform, i + 1)).Concat(itemsAfterRepeater).ToArray();
|
||||
|
||||
// Recurse to translate the synthesized items.
|
||||
container.Shapes.Add(TranslateShapeLayerContents(context, shapeContext, generatedItems));
|
||||
|
@ -1115,7 +1115,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
}
|
||||
}
|
||||
|
||||
var stack = new Stack<ShapeLayerContent>(contents);
|
||||
var stack = new Stack<ShapeLayerContent>(contents.ToArray());
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -1315,7 +1315,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
{
|
||||
// Convert all the shapes in the group to a list of geometries
|
||||
var group = (ShapeGroup)shapeContent;
|
||||
var groupedGeometries = CreateCanvasGeometries(context.Clone(), new Stack<ShapeLayerContent>(group.Items), pathFillType).ToArray();
|
||||
var groupedGeometries = CreateCanvasGeometries(context.Clone(), new Stack<ShapeLayerContent>(group.Items.ToArray()), pathFillType).ToArray();
|
||||
foreach (var geometry in groupedGeometries)
|
||||
{
|
||||
yield return geometry;
|
||||
|
@ -1369,7 +1369,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
Sn.Matrix3x2 transformMatrix,
|
||||
bool optimizeLines)
|
||||
{
|
||||
var beziers = figure.Items.ToArray();
|
||||
var beziers = figure.Items;
|
||||
using (var builder = new CanvasPathBuilder(null))
|
||||
{
|
||||
if (beziers.Length == 0)
|
||||
|
@ -2551,7 +2551,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
compositionAnimation.Duration = _lc.Duration;
|
||||
|
||||
// Get only the key frames that exist from at or just before the animation starts, and end at or just after the animation ends.
|
||||
var trimmedKeyFrames = Optimizer.GetOptimized(Optimizer.GetTrimmed(value.KeyFrames, context.StartTime, context.EndTime)).ToArray();
|
||||
var trimmedKeyFrames = Optimizer.GetOptimized(Optimizer.GetTrimmed(value.KeyFrames.ToArray(), context.StartTime, context.EndTime)).ToArray();
|
||||
|
||||
if (trimmedKeyFrames.Length == 0)
|
||||
{
|
||||
|
@ -2890,7 +2890,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
// Multiply the color animation by the single opacity value.
|
||||
return new Animatable<Color>(
|
||||
initialValue: MultiplyColorByOpacityPercent(color.InitialValue, opacityPercent.InitialValue),
|
||||
keyFrames: color.KeyFrames.Select(kf =>
|
||||
keyFrames: color.KeyFrames.SelectToArray(kf =>
|
||||
new KeyFrame<Color>(
|
||||
kf.Frame,
|
||||
MultiplyColorByOpacityPercent(kf.Value, opacityPercent.InitialValue),
|
||||
|
@ -2926,7 +2926,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
|
|||
// Multiply the single color value by the opacity animation.
|
||||
return new Animatable<Color>(
|
||||
initialValue: MultiplyColorByOpacityPercent(color, opacityPercent.InitialValue),
|
||||
keyFrames: opacityPercent.KeyFrames.Select(kf =>
|
||||
keyFrames: opacityPercent.KeyFrames.SelectToArray(kf =>
|
||||
new KeyFrame<Color>(
|
||||
kf.Frame,
|
||||
MultiplyColorByOpacityPercent(color, kf.Value),
|
||||
|
|
|
@ -95,8 +95,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
from item in items
|
||||
let obj = item.Object
|
||||
where (_ignoreCommentProperties || obj.Comment == null)
|
||||
&& !obj.Properties.PropertyNames.Any()
|
||||
&& !obj.Animators.Any()
|
||||
&& obj.Properties.IsEmpty
|
||||
&& obj.Animators.Count == 0
|
||||
select (item.Node, obj);
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
from item in nodes
|
||||
let obj = item.Object
|
||||
where (_ignoreCommentProperties || obj.Comment == null)
|
||||
&& !obj.Properties.PropertyNames.Any()
|
||||
&& obj.Properties.IsEmpty
|
||||
select (item.Node, obj);
|
||||
|
||||
var grouping =
|
||||
|
|
|
@ -819,7 +819,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
}
|
||||
|
||||
var propertySet = obj.Properties;
|
||||
if (propertySet.PropertyNames.Any())
|
||||
if (!propertySet.IsEmpty)
|
||||
{
|
||||
builder.WriteLine($"{Var} propertySet = {localName}{Deref}Properties;");
|
||||
foreach (var prop in propertySet.ScalarProperties)
|
||||
|
@ -1194,7 +1194,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
{
|
||||
var createCallText = $"_c{Deref}CreateColorBrush({Color(obj.Color)})";
|
||||
|
||||
if (obj.Animators.Any())
|
||||
if (obj.Animators.Count > 0)
|
||||
{
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
WriteCreateAssignment(builder, node, createCallText);
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
// Color brushes that are not animated get names describing their color.
|
||||
// Optimization ensures there will only be one brush for any one non-animated color.
|
||||
var brush = (CompositionColorBrush)obj;
|
||||
if (brush.Animators.Any())
|
||||
if (brush.Animators.Count > 0)
|
||||
{
|
||||
// Brush is animated. Give it a name based on the colors in the animation.
|
||||
var colorAnimation = (ColorKeyFrameAnimation)brush.Animators.Where(a => a.Animation is ColorKeyFrameAnimation).First().Animation;
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
obj.RotationAngleInDegrees.HasValue && obj.RotationAngleInDegrees.Value != 0 &&
|
||||
obj.RotationAxis.HasValue && obj.RotationAxis != Vector3.UnitZ;
|
||||
|
||||
if (!obj.Animators.Any() && !hasNonStandardRotation)
|
||||
if (obj.Animators.Count == 0 && !hasNonStandardRotation)
|
||||
{
|
||||
// Get the values of the properties, and the defaults for properties that are not set.
|
||||
var centerPoint = obj.CenterPoint ?? Vector3.Zero;
|
||||
|
@ -136,7 +136,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
// Convert the properties to a transform matrix. This can reduce the
|
||||
// number of calls needed to initialize the object, and makes finding
|
||||
// and removing redundant containers easier.
|
||||
if (!obj.Animators.Any())
|
||||
if (obj.Animators.Count == 0)
|
||||
{
|
||||
// Get the values for the properties, and the defaults for the properties that are not set.
|
||||
var centerPoint = obj.CenterPoint ?? Vector2.Zero;
|
||||
|
@ -211,8 +211,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
var elidableContainers = containerShapes.Where(n =>
|
||||
{
|
||||
var container = (CompositionContainerShape)n.Object;
|
||||
if (container.Properties.PropertyNames.Any() ||
|
||||
container.Animators.Any() ||
|
||||
if (!container.Properties.IsEmpty ||
|
||||
container.Animators.Count > 0 ||
|
||||
container.CenterPoint != null ||
|
||||
container.Offset != null ||
|
||||
container.RotationAngleInDegrees != null ||
|
||||
|
@ -223,8 +223,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
|
||||
foreach (var child in container.Shapes)
|
||||
{
|
||||
if (child.Properties.PropertyNames.Any() ||
|
||||
child.Animators.Any() ||
|
||||
if (!child.Properties.IsEmpty ||
|
||||
child.Animators.Count > 0 ||
|
||||
child.CenterPoint != null ||
|
||||
child.Offset != null ||
|
||||
child.RotationAngleInDegrees != null ||
|
||||
|
@ -264,8 +264,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
container.RotationAngleInDegrees != null ||
|
||||
container.Scale != null ||
|
||||
container.TransformMatrix != null ||
|
||||
container.Animators.Any() ||
|
||||
container.Properties.PropertyNames.Any())
|
||||
container.Animators.Count > 0 ||
|
||||
!container.Properties.IsEmpty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -336,8 +336,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.CodeGen
|
|||
container.Scale == null &&
|
||||
container.Size == null &&
|
||||
container.TransformMatrix == null &&
|
||||
!container.Animators.Any() &&
|
||||
!container.Properties.PropertyNames.Any();
|
||||
container.Animators.Count == 0 &&
|
||||
container.Properties.IsEmpty;
|
||||
}).ToArray();
|
||||
|
||||
// Pull the children of the container into the parent of the container. Remove the unnecessary containers.
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
|
|||
/// <summary>
|
||||
/// Gets the animators that are bound to this object.
|
||||
/// </summary>
|
||||
public IEnumerable<Animator> Animators => _animators;
|
||||
public IReadOnlyList<Animator> Animators => _animators;
|
||||
|
||||
public AnimationController TryGetAnimationController(string target) =>
|
||||
_animators.Where(a => a.AnimatedProperty == target).Single().Controller;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
@ -34,7 +33,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
|
|||
|
||||
internal IEnumerable<string> PropertyNames => _scalarProperties.Keys.Concat(_vector2Properties.Keys);
|
||||
|
||||
internal bool IsEmpty => !PropertyNames.Any();
|
||||
internal bool IsEmpty => _scalarProperties.Count + _vector2Properties.Count == 0;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CompositionObjectType Type => CompositionObjectType.CompositionPropertySet;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
|
||||
{
|
||||
|
@ -13,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
|
|||
#endif
|
||||
abstract class KeyFrameAnimation<T> : KeyFrameAnimation_
|
||||
{
|
||||
readonly Dictionary<float, KeyFrame> _keyFrames = new Dictionary<float, KeyFrame>();
|
||||
readonly SortedList<float, KeyFrame> _keyFrames = new SortedList<float, KeyFrame>();
|
||||
|
||||
protected private KeyFrameAnimation(KeyFrameAnimation<T> other)
|
||||
: base(other)
|
||||
|
@ -44,7 +43,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
|
|||
_keyFrames.Add(progress, new ValueKeyFrame { Progress = progress, Value = value, Easing = easing });
|
||||
}
|
||||
|
||||
public IEnumerable<KeyFrame> KeyFrames => _keyFrames.Values.OrderBy(kf => kf.Progress);
|
||||
public IEnumerable<KeyFrame> KeyFrames => _keyFrames.Values;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int KeyFrameCount => _keyFrames.Count;
|
||||
|
|
|
@ -8,10 +8,7 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData.Tools
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
public
|
||||
#endif
|
||||
sealed class ListOfNeverNull<T> : IList<T>
|
||||
sealed class ListOfNeverNull<T> : IList<T>, IReadOnlyList<T>
|
||||
{
|
||||
readonly List<T> _wrapped = new List<T>();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче