internal static void Canonicalize(ObjectGraph <TNode> graph, bool ignoreCommentProperties) { var canonicalizer = new CanonicalizerWorker <TNode>(graph, ignoreCommentProperties); canonicalizer.Canonicalize(); }
CanonicalizerWorker(ObjectGraph <TNode> graph, bool ignoreCommentProperties) { _graph = graph; _ignoreCommentProperties = ignoreCommentProperties; }
internal static void Canonicalize <T>(ObjectGraph <T> graph, bool ignoreCommentProperties) where T : CanonicalizedNode <T>, new() { CanonicalizerWorker <T> .Canonicalize(graph, ignoreCommentProperties); }
/// <summary> /// Returns the graph of nodes reachable from the given <see cref="CompositionObject"/> root. /// </summary> /// <returns>A <see cref="Graph"/> from the given Composition tree.</returns> public static ObjectGraph <Node> FromCompositionObject(CompositionObject root, bool includeVertices) => ObjectGraph <Node> .FromCompositionObject(root, includeVertices);
static void CoalesceContainerVisuals(ObjectGraph <Node> graph) { // If a container is not animated and has no properties set, its children can be inserted into its parent. var containersWithNoPropertiesSet = graph.CompositionObjectNodes.Where(n => { // Find the ContainerVisuals that have no properties set. return (n.Object is ContainerVisual container && container.CenterPoint == null && container.Clip == null && container.Offset == null && container.Opacity == null && container.RotationAngleInDegrees == null && container.Scale == null && container.Size == null && container.TransformMatrix == null && container.Animators.Count == 0 && container.Properties.Names.Count == 0); }).ToArray(); // Pull the children of the container into the parent of the container. Remove the unnecessary containers. foreach (var(Node, Object) in containersWithNoPropertiesSet) { var container = (ContainerVisual)Object; // Insert the children into the parent. var parent = (ContainerVisual)Node.Parent; if (parent == null) { // The container may have already been removed, or it might be a root. continue; } // Find the index in the parent of the container. // If childCount is 1, just replace the the container in the parent. // If childCount is >1, insert into the parent. var index = parent.Children.IndexOf(container); // Get the children from the container. var children = container.Children.ToArray(); if (children.Length == 0) { // The container has no children. This is rare but can happen if // the container is for a layer type that we don't support. continue; } // Remove the children from the container. container.Children.Clear(); // Insert the first child where the container was. var child0 = children[0]; CopyDescriptions(container, child0); parent.Children[index] = child0; // Fix the parent pointer in the graph. graph[child0].Parent = parent; // Insert the rest of the children. for (var n = 1; n < children.Length; n++) { var childN = children[n]; CopyDescriptions(container, childN); parent.Children.Insert(index + n, childN); // Fix the parent pointer in the graph. graph[childN].Parent = parent; } } }
static void CoalesceContainerShapes(ObjectGraph <Node> graph) { var containerShapes = graph.CompositionObjectNodes.Where(n => n.Object.Type == CompositionObjectType.CompositionContainerShape).ToArray(); // If a container is not animated and has no other properties set apart from a transform, // and all of its children are also not animated and have no other properties set apart // from a transform, the transform can be pushed down to the child, allowing the parent to be removed. var elidableContainers = containerShapes.Where(n => { var container = (CompositionContainerShape)n.Object; if (container.Properties.Names.Count > 0 || container.Animators.Count > 0 || container.CenterPoint != null || container.Offset != null || container.RotationAngleInDegrees != null || container.Scale != null) { return(false); } foreach (var child in container.Shapes) { if (child.Properties.Names.Count > 0 || child.Animators.Count > 0 || child.CenterPoint != null || child.Offset != null || child.RotationAngleInDegrees != null || child.Scale != null) { return(false); } } return(true); }); // Push the transform down to the child. foreach (var node in elidableContainers) { var container = (CompositionContainerShape)node.Object; foreach (var child in container.Shapes) { // Push the transform down to the child if (container.TransformMatrix.HasValue) { child.TransformMatrix = (child.TransformMatrix ?? Matrix3x2.Identity) * container.TransformMatrix; } } // Remove the transform from the container. container.TransformMatrix = null; } // If a container is not animated and has no properties set, its children can be inserted into its parent. var containersWithNoPropertiesSet = containerShapes.Where(n => { var container = (CompositionContainerShape)n.Object; if (container.Type != CompositionObjectType.CompositionContainerShape || container.CenterPoint != null || container.Offset != null || container.RotationAngleInDegrees != null || container.Scale != null || container.TransformMatrix != null || container.Animators.Count > 0 || container.Properties.Names.Count > 0) { return(false); } // Container has no properties set. return(true); }).ToArray(); foreach (var(Node, Object) in containersWithNoPropertiesSet) { var container = (CompositionContainerShape)Object; // Insert the children into the parent. var parent = (IContainShapes)Node.Parent; if (parent == null) { // The container may have already been removed, or it might be a root. continue; } // Find the index in the parent of the container. // If childCount is 1, just replace the the container in the parent. // If childCount is >1, insert into the parent. var index = parent.Shapes.IndexOf(container); // Get the children from the container. var children = container.Shapes.ToArray(); if (children.Length == 0) { // The container has no children. This is rare but can happen if // the container is for a layer type that we don't support. continue; } // Remove the children from the container. container.Shapes.Clear(); // Insert the first child where the container was. var child0 = children[0]; CopyDescriptions(container, child0); parent.Shapes[index] = child0; // Fix the parent pointer in the graph. graph[child0].Parent = (CompositionObject)parent; // Insert the rest of the children. for (var n = 1; n < children.Length; n++) { var childN = children[n]; CopyDescriptions(container, childN); parent.Shapes.Insert(index + n, childN); // Fix the parent pointer in the graph. graph[childN].Parent = (CompositionObject)parent; } } }