Simplified factories for some common cases. (#278)
* Simplified factories for some common cases. This simplifies the codegen for the creation of some objects. This results in smaller outputs and a slight perf improvement.
This commit is contained in:
Родитель
c544e564c6
Коммит
34367ced9b
|
@ -51,6 +51,39 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.Tools
|
|||
/// </summary>
|
||||
public int Position { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns <c>True</c> iff this node is reachable from the given node.
|
||||
/// </summary>
|
||||
/// <param name="node">The node to test.</param>
|
||||
/// <returns><c>True</c> if this node is reachable from the given node.</returns>
|
||||
public bool IsReachableFrom(Node<T> node) => node is null ? false : IsReachableFrom(node, new HashSet<Node<T>>());
|
||||
|
||||
bool IsReachableFrom(Node<T> targetNode, HashSet<Node<T>> alreadyVisited)
|
||||
{
|
||||
// Walk the tree of references to this node, ignoring any that have already
|
||||
// been visited.
|
||||
foreach (var vertex in targetNode.InReferences)
|
||||
{
|
||||
// inRef is a node that directly references this node.
|
||||
var inRef = vertex.Node;
|
||||
|
||||
if (alreadyVisited.Add(inRef))
|
||||
{
|
||||
// We haven't examined the inRef node yet.
|
||||
if (inRef == targetNode || inRef.IsReachableFrom(targetNode, alreadyVisited))
|
||||
{
|
||||
// inRef is the targetNode, or it's reachable from targetNode.
|
||||
return true;
|
||||
}
|
||||
|
||||
// This node is not reachable from the targetNode.
|
||||
}
|
||||
}
|
||||
|
||||
// Not reachable from targetNode.
|
||||
return false;
|
||||
}
|
||||
|
||||
public struct Vertex
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -2797,20 +2797,28 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen
|
|||
|
||||
bool GenerateCompositionPathGeometryFactory(CodeBuilder builder, CompositionPathGeometry obj, ObjectData node)
|
||||
{
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
if (obj.Path is null)
|
||||
var path = obj.Path is null ? null : _objectGraph[obj.Path];
|
||||
var createPathText = path is null ? string.Empty : CallFactoryFromFor(node, path);
|
||||
var createPathGeometryText = $"_c{Deref}CreatePathGeometry({createPathText})";
|
||||
|
||||
if (obj.Animators.Count == 0 &&
|
||||
obj.Properties.Names.Count == 0 &&
|
||||
!obj.TrimEnd.HasValue &&
|
||||
!obj.TrimOffset.HasValue &&
|
||||
!obj.TrimStart.HasValue &&
|
||||
!node.IsReachableFrom(path))
|
||||
{
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}CreatePathGeometry()");
|
||||
WriteSimpleObjectFactory(builder, node, createPathGeometryText);
|
||||
}
|
||||
else
|
||||
{
|
||||
var path = _objectGraph[obj.Path];
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}CreatePathGeometry({CallFactoryFromFor(node, path)})");
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
WriteCreateAssignment(builder, node, createPathGeometryText);
|
||||
InitializeCompositionGeometry(builder, obj, node);
|
||||
StartAnimationsOnResult(builder, obj, node);
|
||||
WriteObjectFactoryEnd(builder);
|
||||
}
|
||||
|
||||
InitializeCompositionGeometry(builder, obj, node);
|
||||
StartAnimationsOnResult(builder, obj, node);
|
||||
WriteObjectFactoryEnd(builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3009,27 +3017,51 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen
|
|||
|
||||
bool GenerateCompositionSurfaceBrushFactory(CodeBuilder builder, CompositionSurfaceBrush obj, ObjectData node)
|
||||
{
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}CreateSurfaceBrush()");
|
||||
InitializeCompositionBrush(builder, obj, node);
|
||||
|
||||
if (obj.Surface != null)
|
||||
var surfaceNode = obj.Surface switch
|
||||
{
|
||||
switch (obj.Surface)
|
||||
CompositionObject compositionObject => NodeFor(compositionObject),
|
||||
Wmd.LoadedImageSurface loadedImageSurface => NodeFor(loadedImageSurface),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// Create the code that initializes the Surface.
|
||||
var surfaceInitializationText = obj.Surface switch
|
||||
{
|
||||
CompositionObject compositionObject => CallFactoryFromFor(node, compositionObject),
|
||||
Wmd.LoadedImageSurface _ => surfaceNode.FieldName,
|
||||
null => string.Empty,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
|
||||
var isReachableFromSurfaceNode = node.IsReachableFrom(surfaceNode);
|
||||
|
||||
if (obj.Animators.Count == 0 &&
|
||||
obj.Properties.Names.Count == 0 &&
|
||||
!isReachableFromSurfaceNode)
|
||||
{
|
||||
WriteSimpleObjectFactory(builder, node, $"_c{Deref}CreateSurfaceBrush({surfaceInitializationText})");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObjectFactoryStart(builder, node);
|
||||
|
||||
if (isReachableFromSurfaceNode)
|
||||
{
|
||||
case CompositionObject compositionObject:
|
||||
WriteSetPropertyStatement(builder, "Surface", CallFactoryFromFor(node, compositionObject));
|
||||
break;
|
||||
case Wmd.LoadedImageSurface loadedImageSurface:
|
||||
WriteSetPropertyStatement(builder, "Surface", NodeFor(loadedImageSurface).FieldName);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
// The Surface depends on the brush, so the brush needs to be created and assigned
|
||||
// before the Surface.
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}CreateSurfaceBrush()");
|
||||
WriteSetPropertyStatement(builder, "Surface", surfaceInitializationText);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteCreateAssignment(builder, node, $"_c{Deref}CreateSurfaceBrush({surfaceInitializationText})");
|
||||
}
|
||||
|
||||
InitializeCompositionBrush(builder, obj, node);
|
||||
StartAnimationsOnResult(builder, obj, node);
|
||||
WriteObjectFactoryEnd(builder);
|
||||
}
|
||||
|
||||
StartAnimationsOnResult(builder, obj, node);
|
||||
WriteObjectFactoryEnd(builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче