[gtk/path-work-rebased: 78/118] ottie: Add a snapshot testsuite test




commit c7c8442a290e53290ce480d8a51e8aeb5e53209d
Author: Benjamin Otte <otte redhat com>
Date:   Sun Dec 20 00:18:14 2020 +0100

    ottie: Add a snapshot testsuite test
    
    The test takes a lottie file and a timestamp in seconds and produces a
    rendernode at that timestamp.
    
    It then serializes that node and compares it via diff(1) with a file
    containing the expected output.
    
    This is a lot stricter than it needs to be (because different node files
    can generate the same output and updates to the rendering pipeline can
    break everything) but I chose this method on purpose because it does a
    good job at guarding against accidental changes in other parts of the
    code.
    
    It's also better than comparing image output because it avoids
    antialiasing artifacts when using curves and things like that.

 testsuite/meson.build                              |    1 +
 testsuite/ottie/meson.build                        |   48 +
 testsuite/ottie/snapshot.c                         |  181 ++
 .../ottie/snapshot/color-array-not-an-array.0.node |    9 +
 .../snapshot/color-array-not-an-array.lottie.json  |  130 ++
 .../snapshot/color-array-size-too-small.0.node     |    9 +
 .../color-array-size-too-small.lottie.json         |  133 ++
 testsuite/ottie/snapshot/color-has-no-alpha.0.node |    9 +
 .../ottie/snapshot/color-has-no-alpha.lottie.json  |  135 ++
 .../ottie/snapshot/composition-clipping.0.node     |   29 +
 .../snapshot/composition-clipping.lottie.json      |    1 +
 testsuite/ottie/snapshot/composition-simple.0.node |   15 +
 .../ottie/snapshot/composition-simple.lottie.json  |    1 +
 .../ottie/snapshot/composition-stacking.0.node     |   87 +
 .../snapshot/composition-stacking.lottie.json      |    1 +
 .../snapshot/composition-time-properties.0.node    |   27 +
 .../snapshot/composition-time-properties.1.node    |   42 +
 .../snapshot/composition-time-properties.2.node    |   12 +
 .../composition-time-properties.lottie.json        |    1 +
 .../ottie/snapshot/default-stacking-order.0.node   |   18 +
 .../snapshot/default-stacking-order.lottie.json    |  255 +++
 testsuite/ottie/snapshot/parent-transform.0.node   |  104 ++
 .../ottie/snapshot/parent-transform.lottie.json    |  348 ++++
 .../snapshot/paths-respect-group-transform.0.node  |   30 +
 .../paths-respect-group-transform.lottie.json      |    1 +
 testsuite/ottie/snapshot/rect-path-order.0.node    |  261 +++
 .../ottie/snapshot/rect-path-order.lottie.json     | 1816 ++++++++++++++++++++
 .../snapshot/trim-0-to-100-shows-everything.0.node |   16 +
 .../trim-0-to-100-shows-everything.lottie.json     |  222 +++
 .../trim-0-to-200-shows-everything-once.0.node     |   16 +
 ...trim-0-to-200-shows-everything-once.lottie.json |  222 +++
 .../ottie/snapshot/trim-equal-is-empty.0.node      |    0
 .../ottie/snapshot/trim-equal-is-empty.lottie.json |  247 +++
 .../ottie/snapshot/trim-offset-rotates.0.node      |   18 +
 .../ottie/snapshot/trim-offset-rotates.lottie.json |  222 +++
 .../snapshot/trim-startend-does-minmax.0.node      |   16 +
 .../snapshot/trim-startend-does-minmax.lottie.json |  222 +++
 testsuite/ottie/snapshot/two-shapes.0.node         |   27 +
 testsuite/ottie/snapshot/two-shapes.lottie.json    |    1 +
 39 files changed, 4933 insertions(+)
---
diff --git a/testsuite/meson.build b/testsuite/meson.build
index 97344f3062..47f69f2339 100644
--- a/testsuite/meson.build
+++ b/testsuite/meson.build
@@ -56,6 +56,7 @@ subdir('performance')
 subdir('gdk')
 subdir('gsk')
 subdir('gtk')
+subdir('ottie')
 subdir('css')
 subdir('a11y')
 subdir('tools')
diff --git a/testsuite/ottie/meson.build b/testsuite/ottie/meson.build
new file mode 100644
index 0000000000..7b7b8e7a8a
--- /dev/null
+++ b/testsuite/ottie/meson.build
@@ -0,0 +1,48 @@
+testexecdir = join_paths(installed_test_bindir, 'gsk')
+testdatadir = join_paths(installed_test_datadir, 'gsk')
+
+snapshot = executable(
+  'snapshot',
+  ['snapshot.c'],
+  dependencies: libgtk_dep,
+  c_args: common_cflags,
+  install: get_option('install-tests'),
+  install_dir: testexecdir
+)
+
+snapshot_tests = [
+  [ 'color-has-no-alpha', 0 ],
+  [ 'color-array-not-an-array', 0 ],
+  [ 'color-array-size-too-small', 0 ],
+  [ 'composition-clipping', 0 ],
+  [ 'composition-simple', 0 ],
+  [ 'composition-stacking', 0 ],
+  [ 'composition-time-properties', 0 ],
+  [ 'composition-time-properties', 1 ],
+  [ 'composition-time-properties', 2 ],
+  [ 'default-stacking-order', 0 ],
+  [ 'paths-respect-group-transform', 0 ],
+  [ 'rect-path-order', 0 ],
+  [ 'trim-equal-is-empty', 0 ],
+  [ 'trim-0-to-100-shows-everything', 0 ],
+  [ 'trim-0-to-200-shows-everything-once', 0 ],
+  [ 'trim-startend-does-minmax', 0 ],
+  [ 'trim-offset-rotates', 0 ],
+  [ 'two-shapes', 0 ],
+]
+
+foreach test : snapshot_tests
+  test('snapshot-' + test[0] + '-' + test[1].to_string(), snapshot,
+    args: [
+      '--time=' + test[1].to_string(),
+      join_paths(meson.current_source_dir(), 'snapshot', test[0] + '.lottie.json'),
+      join_paths(meson.current_source_dir(), 'snapshot', test[0] + '.' + test[1].to_string() + '.node'),
+    ],
+    env: [
+      'GTK_A11Y=test',
+      'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
+      'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
+    ],
+    suite: [ 'ottie' ],
+  )
+endforeach
diff --git a/testsuite/ottie/snapshot.c b/testsuite/ottie/snapshot.c
new file mode 100644
index 0000000000..433c7edc71
--- /dev/null
+++ b/testsuite/ottie/snapshot.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include <ottie/ottie.h>
+#include <gtk/gtk.h>
+
+static int
+usage (void)
+{
+  g_print ("Usage:\n"
+           "snapshot [OPTION…] TEST REFERENCE\n"
+           "  Compare a snapshot of TEST to the REFERENCE.\n"
+           "  --time=[timestamp]  Forward to [timestamp] seconds\n"
+           "\n");
+
+  return 1;
+}
+             
+static GBytes *
+diff_with_file (const char  *file1,
+                GBytes      *input,
+                GError     **error)
+{
+  GSubprocess *process;
+  GBytes *output;
+
+  process = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE
+                              | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
+                              error,
+                              "diff", "-u", file1, "-", NULL);
+  if (process == NULL)
+    return NULL;
+
+  if (!g_subprocess_communicate (process,
+                                 input,
+                                 NULL,
+                                 &output,
+                                 NULL,
+                                 error))
+    {
+      g_object_unref (process);
+      return NULL;
+    }
+
+  if (!g_subprocess_get_successful (process) &&
+      /* this is the condition when the files differ */
+      !(g_subprocess_get_if_exited (process) && g_subprocess_get_exit_status (process) == 1))
+    {
+      g_clear_pointer (&output, g_bytes_unref);
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "The `diff' process exited with error status %d",
+                   g_subprocess_get_exit_status (process));
+    }
+
+  g_object_unref (process);
+
+  return output;
+}
+
+static gboolean
+test (const char *testfile,
+      const char *reffile,
+      gint64      timestamp)
+{
+  OttieCreation *ottie;
+  OttiePaintable *paintable;
+  GtkSnapshot *snapshot;
+  GskRenderNode *node;
+  GBytes *bytes, *diff;
+  GError *error = NULL;
+
+  ottie = ottie_creation_new_for_filename (testfile);
+  if (ottie == NULL)
+    {
+      g_printerr ("Someone figure out error handling for loading ottie files.\n");
+      return FALSE;
+    }
+  while (ottie_creation_is_loading (ottie))
+    g_main_context_iteration (NULL, TRUE);
+
+  paintable = ottie_paintable_new (ottie);
+  ottie_paintable_set_timestamp (paintable, timestamp);
+
+  snapshot = gtk_snapshot_new ();
+  gdk_paintable_snapshot (GDK_PAINTABLE (paintable),
+                          snapshot,
+                          ottie_creation_get_width (ottie),
+                          ottie_creation_get_height (ottie));
+  node = gtk_snapshot_free_to_node (snapshot);
+  if (node != NULL)
+    {
+      bytes = gsk_render_node_serialize (node);
+      gsk_render_node_unref (node);
+    }
+  else
+    bytes = g_bytes_new_static ("", 0);
+
+  diff = diff_with_file (reffile, bytes, &error);
+
+  g_bytes_unref (bytes);
+  g_object_unref (paintable);
+
+  if (diff == NULL)
+    {
+      g_printerr ("Error diffing: %s\n", error->message);
+      g_clear_error (&error);
+      return FALSE;
+    }
+
+  if (diff && g_bytes_get_size (diff) > 0)
+    {
+      g_print ("Resulting file doesn't match reference:\n%s\n",
+               (const char *) g_bytes_get_data (diff, NULL));
+      g_bytes_unref (diff);
+      return FALSE;
+    }
+
+  g_bytes_unref (diff);
+  return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+  guint timestamp = 0;
+  int result;
+
+  gtk_test_init (&argc, &argv);
+
+  argc--;
+  argv++;
+
+  while (TRUE)
+    {
+      if (argc == 0)
+        return usage();
+
+      if (strncmp (argv[0], "--time=", strlen ("--time=")) == 0)
+        {
+          timestamp = atof (argv[0] + strlen ("--time="));
+        }
+      else
+        break;
+
+      argc--;
+      argv++;
+    }
+  
+  if (argc % 2 != 0)
+    return usage ();
+
+  result = 0;
+  for (int i = 0; i < argc / 2; i++)
+    {
+      if (!test (argv[2 * i],
+                 argv[2 * i + 1],
+                 round (timestamp * G_USEC_PER_SEC)))
+        result++;
+    }
+
+  return result;
+}
+
diff --git a/testsuite/ottie/snapshot/color-array-not-an-array.0.node 
b/testsuite/ottie/snapshot/color-array-not-an-array.0.node
new file mode 100644
index 0000000000..6ca286872d
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-array-not-an-array.0.node
@@ -0,0 +1,9 @@
+fill {
+  child: color {
+    bounds: 20 20 60 60;
+    color: rgb(0,0,0);
+  }
+  path: "\
+M 20 20 h 60 v 60 h -60 z";
+  fill-rule: winding;
+}
diff --git a/testsuite/ottie/snapshot/color-array-not-an-array.lottie.json 
b/testsuite/ottie/snapshot/color-array-not-an-array.lottie.json
new file mode 100644
index 0000000000..bbe76f6b87
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-array-not-an-array.lottie.json
@@ -0,0 +1,130 @@
+{
+"v": "5.5.2",
+"ip": 0,
+"op": 180,
+"nm": "Animation",
+"mn": "{828cb955-8a2d-4494-badb-935628ead9a0}",
+"fr": 60,
+"w": 100,
+"h": 100,
+"assets": [
+],
+"layers": [
+    {
+        "ddd": 0,
+        "ty": 4,
+        "ip": 0,
+        "op": 180,
+        "st": 0,
+        "ks": {
+            "a": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "p": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "s": {
+                "a": 0,
+                "k": [
+                    100,
+                    100
+                ]
+            },
+            "r": {
+                "a": 0,
+                "k": 0
+            },
+            "o": {
+                "a": 0,
+                "k": 100
+            }
+        },
+        "shapes": [
+            {
+                "ty": "gr",
+                "nm": "Rectangle Group",
+                "mn": "{2101e829-0fd4-4cd3-8220-cd1ef92380c0}",
+                "it": [
+                    {
+                        "ty": "rc",
+                        "nm": "Rectangle",
+                        "mn": "{7db2a541-6f01-4a0e-b7ba-b4bf9501d2b1}",
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                50,
+                                50
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                60,
+                                60
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        }
+                    },
+                    {
+                        "ty": "fl",
+                        "nm": "Rectangle Fill",
+                        "mn": "{31322740-fb76-4406-bf47-625cc7b2e68f}",
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        },
+                        "c": {
+                            "a": 0,
+                            "k": 0.5
+                        },
+                        "r": 1
+                    },
+                    {
+                        "ty": "tr",
+                        "a": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                100,
+                                100
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        },
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]
+}
diff --git a/testsuite/ottie/snapshot/color-array-size-too-small.0.node 
b/testsuite/ottie/snapshot/color-array-size-too-small.0.node
new file mode 100644
index 0000000000..6ca286872d
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-array-size-too-small.0.node
@@ -0,0 +1,9 @@
+fill {
+  child: color {
+    bounds: 20 20 60 60;
+    color: rgb(0,0,0);
+  }
+  path: "\
+M 20 20 h 60 v 60 h -60 z";
+  fill-rule: winding;
+}
diff --git a/testsuite/ottie/snapshot/color-array-size-too-small.lottie.json 
b/testsuite/ottie/snapshot/color-array-size-too-small.lottie.json
new file mode 100644
index 0000000000..e3146618da
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-array-size-too-small.lottie.json
@@ -0,0 +1,133 @@
+{
+"v": "5.5.2",
+"ip": 0,
+"op": 180,
+"nm": "Animation",
+"mn": "{828cb955-8a2d-4494-badb-935628ead9a0}",
+"fr": 60,
+"w": 100,
+"h": 100,
+"assets": [
+],
+"layers": [
+    {
+        "ddd": 0,
+        "ty": 4,
+        "ip": 0,
+        "op": 180,
+        "st": 0,
+        "ks": {
+            "a": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "p": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "s": {
+                "a": 0,
+                "k": [
+                    100,
+                    100
+                ]
+            },
+            "r": {
+                "a": 0,
+                "k": 0
+            },
+            "o": {
+                "a": 0,
+                "k": 100
+            }
+        },
+        "shapes": [
+            {
+                "ty": "gr",
+                "nm": "Rectangle Group",
+                "mn": "{2101e829-0fd4-4cd3-8220-cd1ef92380c0}",
+                "it": [
+                    {
+                        "ty": "rc",
+                        "nm": "Rectangle",
+                        "mn": "{7db2a541-6f01-4a0e-b7ba-b4bf9501d2b1}",
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                50,
+                                50
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                60,
+                                60
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        }
+                    },
+                    {
+                        "ty": "fl",
+                        "nm": "Rectangle Fill",
+                        "mn": "{31322740-fb76-4406-bf47-625cc7b2e68f}",
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        },
+                        "c": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                1
+                            ]
+                        },
+                        "r": 1
+                    },
+                    {
+                        "ty": "tr",
+                        "a": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                100,
+                                100
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        },
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]
+}
diff --git a/testsuite/ottie/snapshot/color-has-no-alpha.0.node 
b/testsuite/ottie/snapshot/color-has-no-alpha.0.node
new file mode 100644
index 0000000000..74129e9111
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-has-no-alpha.0.node
@@ -0,0 +1,9 @@
+fill {
+  child: color {
+    bounds: 20 20 60 60;
+    color: rgb(0,255,0);
+  }
+  path: "\
+M 20 20 h 60 v 60 h -60 z";
+  fill-rule: winding;
+}
diff --git a/testsuite/ottie/snapshot/color-has-no-alpha.lottie.json 
b/testsuite/ottie/snapshot/color-has-no-alpha.lottie.json
new file mode 100644
index 0000000000..61418568ad
--- /dev/null
+++ b/testsuite/ottie/snapshot/color-has-no-alpha.lottie.json
@@ -0,0 +1,135 @@
+{
+"v": "5.5.2",
+"ip": 0,
+"op": 180,
+"nm": "Animation",
+"mn": "{828cb955-8a2d-4494-badb-935628ead9a0}",
+"fr": 60,
+"w": 100,
+"h": 100,
+"assets": [
+],
+"layers": [
+    {
+        "ddd": 0,
+        "ty": 4,
+        "ip": 0,
+        "op": 180,
+        "st": 0,
+        "ks": {
+            "a": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "p": {
+                "a": 0,
+                "k": [
+                    0,
+                    0
+                ]
+            },
+            "s": {
+                "a": 0,
+                "k": [
+                    100,
+                    100
+                ]
+            },
+            "r": {
+                "a": 0,
+                "k": 0
+            },
+            "o": {
+                "a": 0,
+                "k": 100
+            }
+        },
+        "shapes": [
+            {
+                "ty": "gr",
+                "nm": "Rectangle Group",
+                "mn": "{2101e829-0fd4-4cd3-8220-cd1ef92380c0}",
+                "it": [
+                    {
+                        "ty": "rc",
+                        "nm": "Rectangle",
+                        "mn": "{7db2a541-6f01-4a0e-b7ba-b4bf9501d2b1}",
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                50,
+                                50
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                60,
+                                60
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        }
+                    },
+                    {
+                        "ty": "fl",
+                        "nm": "Rectangle Fill",
+                        "mn": "{31322740-fb76-4406-bf47-625cc7b2e68f}",
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        },
+                        "c": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                1,
+                                0,
+                                0
+                            ]
+                        },
+                        "r": 1
+                    },
+                    {
+                        "ty": "tr",
+                        "a": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "p": {
+                            "a": 0,
+                            "k": [
+                                0,
+                                0
+                            ]
+                        },
+                        "s": {
+                            "a": 0,
+                            "k": [
+                                100,
+                                100
+                            ]
+                        },
+                        "r": {
+                            "a": 0,
+                            "k": 0
+                        },
+                        "o": {
+                            "a": 0,
+                            "k": 100
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]
+}
diff --git a/testsuite/ottie/snapshot/composition-clipping.0.node 
b/testsuite/ottie/snapshot/composition-clipping.0.node
new file mode 100644
index 0000000000..28bd0eea06
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-clipping.0.node
@@ -0,0 +1,29 @@
+transform {
+  child: clip {
+    child: transform {
+      child: container {
+        fill {
+          child: color {
+            bounds: -256 -256 512 512;
+            color: rgb(255,255,0);
+          }
+          path: "\
+M -256 -256 h 512 v 512 h -512 z";
+          fill-rule: winding;
+        }
+        fill {
+          child: color {
+            bounds: -128 -64 256 128;
+            color: rgb(255,0,0);
+          }
+          path: "\
+M -128 -64 h 256 v 128 h -256 z";
+          fill-rule: winding;
+        }
+      }
+      transform: translate(256, 256);
+    }
+    clip: 0 0 200 200;
+  }
+  transform: translate(128, 128) scale(1.5, 0.5);
+}
diff --git a/testsuite/ottie/snapshot/composition-clipping.lottie.json 
b/testsuite/ottie/snapshot/composition-clipping.lottie.json
new file mode 100644
index 0000000000..02382ee795
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-clipping.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{a7788046-ae0d-480b-af8c-882fe92c5abe}","fr":60.000,"w":512,"h":512,"assets":[{"nm":"Composition","mn":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","id":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":180.000,"nm":"Layer
 
1","mn":"{c3d1100f-cf12-4e09-a100-39dbd0dd3bdc}","ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"gr","nm":"Rectangle
 Group 
1","mn":"{0715912e-e1dc-4f28-9cc9-323a5ae7c125}","it":[{"ty":"rc","nm":"Rectangle","mn":"{bbfc6b21-ac6b-4089-ac1e-514cdd5797f0}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[256.000,128.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 Fill 
1","mn":"{fc049e27-f329-4d07-a42e-c22f5d85d3a6}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,0.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[
 
0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]},{"ty":"gr","nm":"Rectangle
 Group","mn":"{59b9ff60-a626-47b3-8447-617461bf3f07}","it":[{"ty":"rc","nm":"Rectangle 
1","mn":"{fb85e667-0469-41fa-ba89-f35230fad8d3}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[512.000,512.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 
Fill","mn":"{b92ab183-7416-40d1-b9af-cd4e5440ae3a}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,1.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]}]}]}],"layers":[{"ty":0,"ddd":0,"nm":"Composition
 
Layer","mn":"{50c7cf81-8979-433b-b715-c9362ed98fca}","ip":0.000,"op":180.000,"ind":1,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[128.000,128.000]},"s":{"a":0,"k":[150.000,50.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{04b02eda-5acd-4ef0-b6ee-d11c9
 38fc501}","w":200.000,"h":200.000}]}
\ No newline at end of file
diff --git a/testsuite/ottie/snapshot/composition-simple.0.node 
b/testsuite/ottie/snapshot/composition-simple.0.node
new file mode 100644
index 0000000000..6d8de49530
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-simple.0.node
@@ -0,0 +1,15 @@
+clip {
+  child: transform {
+    child: fill {
+      child: color {
+        bounds: -128 -64 256 128;
+        color: rgb(255,0,0);
+      }
+      path: "\
+M -128 -64 h 256 v 128 h -256 z";
+      fill-rule: winding;
+    }
+    transform: translate(256, 256);
+  }
+  clip: 0 0 512 512;
+}
diff --git a/testsuite/ottie/snapshot/composition-simple.lottie.json 
b/testsuite/ottie/snapshot/composition-simple.lottie.json
new file mode 100644
index 0000000000..a1a47bffc7
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-simple.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{a7788046-ae0d-480b-af8c-882fe92c5abe}","fr":60.000,"w":512,"h":512,"assets":[{"nm":"Composition","mn":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","id":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":180.000,"nm":"Layer
 
1","mn":"{c3d1100f-cf12-4e09-a100-39dbd0dd3bdc}","ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"gr","nm":"Rectangle
 Group 1","mn":"{0715912e-e1dc-4f28-9cc9-323a5ae7c125}","it":[{"ty":"rc","nm":"Rectangle 
1","mn":"{bfddb11d-73b0-4b6f-aec7-41bd2c2124df}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[256.000,128.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 Fill 
1","mn":"{fc049e27-f329-4d07-a42e-c22f5d85d3a6}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,0.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k"
 
:[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]}]}]}],"layers":[{"ty":0,"ddd":0,"nm":"Composition
 
Layer","mn":"{50c7cf81-8979-433b-b715-c9362ed98fca}","ip":0.000,"op":180.000,"ind":1,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","w":512.000,"h":512.000}]}
\ No newline at end of file
diff --git a/testsuite/ottie/snapshot/composition-stacking.0.node 
b/testsuite/ottie/snapshot/composition-stacking.0.node
new file mode 100644
index 0000000000..a8713ce8d7
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-stacking.0.node
@@ -0,0 +1,87 @@
+transform {
+  child: clip {
+    child: transform {
+      child: container {
+        fill {
+          child: color {
+            bounds: -32 -32 64 64;
+            color: rgb(255,0,0);
+          }
+          path: "\
+M -32 -32 h 64 v 64 h -64 z";
+          fill-rule: winding;
+        }
+        fill {
+          child: color {
+            bounds: -32 -16 64 32;
+            color: rgb(255,255,0);
+          }
+          path: "\
+M -32 -16 h 64 v 32 h -64 z";
+          fill-rule: winding;
+        }
+      }
+      transform: translate(64, 64);
+    }
+    clip: 0 0 200 200;
+  }
+  transform: translate(64, 64) scale(3);
+}
+transform {
+  child: clip {
+    child: transform {
+      child: container {
+        fill {
+          child: color {
+            bounds: -32 -32 64 64;
+            color: rgb(255,0,0);
+          }
+          path: "\
+M -32 -32 h 64 v 64 h -64 z";
+          fill-rule: winding;
+        }
+        fill {
+          child: color {
+            bounds: -32 -16 64 32;
+            color: rgb(255,255,0);
+          }
+          path: "\
+M -32 -16 h 64 v 32 h -64 z";
+          fill-rule: winding;
+        }
+      }
+      transform: translate(64, 64);
+    }
+    clip: 0 0 200 200;
+  }
+  transform: translate(64, 64) scale(2);
+}
+transform {
+  child: clip {
+    child: transform {
+      child: container {
+        fill {
+          child: color {
+            bounds: -32 -32 64 64;
+            color: rgb(255,0,0);
+          }
+          path: "\
+M -32 -32 h 64 v 64 h -64 z";
+          fill-rule: winding;
+        }
+        fill {
+          child: color {
+            bounds: -32 -16 64 32;
+            color: rgb(255,255,0);
+          }
+          path: "\
+M -32 -16 h 64 v 32 h -64 z";
+          fill-rule: winding;
+        }
+      }
+      transform: translate(64, 64);
+    }
+    clip: 0 0 200 200;
+  }
+  transform: translate(64, 64) scale(4);
+}
diff --git a/testsuite/ottie/snapshot/composition-stacking.lottie.json 
b/testsuite/ottie/snapshot/composition-stacking.lottie.json
new file mode 100644
index 0000000000..071e2a6206
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-stacking.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{a7788046-ae0d-480b-af8c-882fe92c5abe}","fr":60.000,"w":512,"h":512,"assets":[{"nm":"Composition","mn":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","id":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":180.000,"nm":"Layer
 
1","mn":"{c3d1100f-cf12-4e09-a100-39dbd0dd3bdc}","ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[64.000,64.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"gr","nm":"Rectangle
 Group 
1","mn":"{0715912e-e1dc-4f28-9cc9-323a5ae7c125}","it":[{"ty":"rc","nm":"Rectangle","mn":"{bbfc6b21-ac6b-4089-ac1e-514cdd5797f0}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[64.000,32.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 Fill 
1","mn":"{fc049e27-f329-4d07-a42e-c22f5d85d3a6}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,1.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.00
 
0,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]},{"ty":"gr","nm":"Rectangle
 Group","mn":"{59b9ff60-a626-47b3-8447-617461bf3f07}","it":[{"ty":"rc","nm":"Rectangle 
1","mn":"{fb85e667-0469-41fa-ba89-f35230fad8d3}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[64.000,64.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 
Fill","mn":"{b92ab183-7416-40d1-b9af-cd4e5440ae3a}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,0.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]}]}]}],"layers":[{"ty":0,"ddd":0,"nm":"Composition
 Layer 
2","mn":"{3afbe39b-d1ba-42e2-a923-1f6e5ed7521b}","ip":0.000,"op":180.000,"ind":3,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[64.000,64.000]},"s":{"a":0,"k":[400.000,400.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{04b02eda-5acd-4ef0-b6ee-d11c938fc5
 01}","w":200.000,"h":200.000},{"ty":0,"ddd":0,"nm":"Composition Layer 
1","mn":"{c98a907a-c55d-49ef-bd2d-d07cfde40ed1}","ip":0.000,"op":180.000,"ind":2,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[64.000,64.000]},"s":{"a":0,"k":[200.000,200.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","w":200.000,"h":200.000},{"ty":0,"ddd":0,"nm":"Composition
 
Layer","mn":"{50c7cf81-8979-433b-b715-c9362ed98fca}","ip":0.000,"op":180.000,"ind":1,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[64.000,64.000]},"s":{"a":0,"k":[300.000,300.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{04b02eda-5acd-4ef0-b6ee-d11c938fc501}","w":200.000,"h":200.000}]}
\ No newline at end of file
diff --git a/testsuite/ottie/snapshot/composition-time-properties.0.node 
b/testsuite/ottie/snapshot/composition-time-properties.0.node
new file mode 100644
index 0000000000..1d54b5b8f9
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-time-properties.0.node
@@ -0,0 +1,27 @@
+clip {
+  child: fill {
+    child: color {
+      bounds: 128 192 256 128;
+      color: rgb(255,255,0);
+    }
+    path: "\
+M 128 192 h 256 v 128 h -256 z";
+    fill-rule: winding;
+  }
+  clip: 0 0 512 512;
+}
+transform {
+  child: clip {
+    child: fill {
+      child: color {
+        bounds: 128 192 256 128;
+        color: rgb(255,255,0);
+      }
+      path: "\
+M 128 192 h 256 v 128 h -256 z";
+      fill-rule: winding;
+    }
+    clip: 0 0 512 512;
+  }
+  transform: translate(0, -128);
+}
diff --git a/testsuite/ottie/snapshot/composition-time-properties.1.node 
b/testsuite/ottie/snapshot/composition-time-properties.1.node
new file mode 100644
index 0000000000..0a722a6a69
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-time-properties.1.node
@@ -0,0 +1,42 @@
+transform {
+  child: clip {
+    child: fill {
+      child: color {
+        bounds: 128 192 256 128;
+        color: rgb(128,128,128);
+      }
+      path: "\
+M 128 192 h 256 v 128 h -256 z";
+      fill-rule: winding;
+    }
+    clip: 0 0 512 512;
+  }
+  transform: translate(0, 128);
+}
+clip {
+  child: fill {
+    child: color {
+      bounds: 128 192 256 128;
+      color: rgb(128,128,128);
+    }
+    path: "\
+M 128 192 h 256 v 128 h -256 z";
+    fill-rule: winding;
+  }
+  clip: 0 0 512 512;
+}
+transform {
+  child: clip {
+    child: fill {
+      child: color {
+        bounds: 128 192 256 128;
+        color: rgb(0,0,255);
+      }
+      path: "\
+M 128 192 h 256 v 128 h -256 z";
+      fill-rule: winding;
+    }
+    clip: 0 0 512 512;
+  }
+  transform: translate(0, -128);
+}
diff --git a/testsuite/ottie/snapshot/composition-time-properties.2.node 
b/testsuite/ottie/snapshot/composition-time-properties.2.node
new file mode 100644
index 0000000000..10e7f0a1ba
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-time-properties.2.node
@@ -0,0 +1,12 @@
+clip {
+  child: fill {
+    child: color {
+      bounds: 128 192 256 128;
+      color: rgb(0,0,255);
+    }
+    path: "\
+M 128 192 h 256 v 128 h -256 z";
+    fill-rule: winding;
+  }
+  clip: 0 0 512 512;
+}
diff --git a/testsuite/ottie/snapshot/composition-time-properties.lottie.json 
b/testsuite/ottie/snapshot/composition-time-properties.lottie.json
new file mode 100644
index 0000000000..4047b3885e
--- /dev/null
+++ b/testsuite/ottie/snapshot/composition-time-properties.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{b2d5b1f5-de9a-40f2-a1de-6402b93caf46}","fr":60.000,"w":512,"h":512,"assets":[{"nm":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","mn":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","id":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":60.000,"nm":"Layer","mn":"{8e705fc4-fcca-419d-9703-f1794f124410}","ks":{"a":{"a":0,"k":[256.000,256.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"rc","nm":"Rectangle","mn":"{d5e80796-ec16-48d7-af21-b7c74cab5d86}","p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[256.000,128.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 
Fill","mn":"{ddf1d012-3cf4-4264-8156-f35690d4c4c7}","o":{"a":0,"k":100.000},"c":{"a":1,"k":[{"t":0.000,"s":[1.000,1.000,0.000,1.000],"h":0,"i":{"x":[0.000],"y":[0.000]},"o":{"x":[0.000],"y":[0.000]},"e":[0.000,0.000,1.000,1.000]},{"t":60.00
 0,"s":[0.000,0.000,1.000,1.000]}]},"r":1}]}]}],"layers":[{"ty":0,"ddd":0,"nm":"Composition Layer 
2","mn":"{999288f4-c0bd-4d4c-852a-a5e8d6d8145b}","ip":0.000,"op":180.000,"ind":3,"st":0.000,"sr":1.000,"ks":{"a":{"a":0,"k":[256.000,256.000]},"p":{"a":0,"k":[256.000,128.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","w":512.000,"h":512.000},{"ty":0,"ddd":0,"nm":"Composition
 
Layer","mn":"{95cd6bf0-78b9-401b-a870-63dedfa6c4cb}","ip":0.000,"op":180.000,"ind":2,"st":0.000,"sr":2.000,"ks":{"a":{"a":0,"k":[256.000,256.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","w":512.000,"h":512.000},{"ty":0,"ddd":0,"nm":"Composition
 Layer 
1","mn":"{e84c5aa4-8142-41f8-8789-ee66ebb1608a}","ip":0.000,"op":180.000,"ind":1,"st":30.000,"sr":1.000,"ks":{"a":{"a":0,"k":[256.000,256.000]},"p":{"a":0,"k"
 
:[256.000,384.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"refId":"{5f5f6e69-b493-4591-9f28-b2f34683cdcc}","w":512.000,"h":512.000}]}
\ No newline at end of file
diff --git a/testsuite/ottie/snapshot/default-stacking-order.0.node 
b/testsuite/ottie/snapshot/default-stacking-order.0.node
new file mode 100644
index 0000000000..6cbf1772f1
--- /dev/null
+++ b/testsuite/ottie/snapshot/default-stacking-order.0.node
@@ -0,0 +1,18 @@
+fill {
+  child: color {
+    bounds: 40 20 20 60;
+    color: rgb(0,255,0);
+  }
+  path: "\
+M 40 20 h 20 v 60 h -20 z";
+  fill-rule: winding;
+}
+fill {
+  child: color {
+    bounds: 20 40 60 20;
+    color: rgb(255,0,0);
+  }
+  path: "\
+M 20 40 h 60 v 20 h -60 z";
+  fill-rule: winding;
+}
diff --git a/testsuite/ottie/snapshot/default-stacking-order.lottie.json 
b/testsuite/ottie/snapshot/default-stacking-order.lottie.json
new file mode 100644
index 0000000000..a37ec6b593
--- /dev/null
+++ b/testsuite/ottie/snapshot/default-stacking-order.lottie.json
@@ -0,0 +1,255 @@
+{
+  "v" : "5.5.2",
+  "ip" : 0.0,
+  "op" : 180.0,
+  "nm" : "Animation",
+  "mn" : "{828cb955-8a2d-4494-badb-935628ead9a0}",
+  "fr" : 60.0,
+  "w" : 100,
+  "h" : 100,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ty" : 4,
+      "ip" : 0.0,
+      "op" : 180.0,
+      "st" : 0,
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100
+        }
+      },
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "nm" : "Rectangle 1 Group",
+          "mn" : "{e9ee5ac8-191c-4c91-9810-f41801aefd11}",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rectangle 1",
+              "mn" : "{065abe56-76de-4f28-b36d-44c9a39298ae}",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  50.0,
+                  50.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                      60.0,
+                      20.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              }
+            },
+            {
+              "ty" : "fl",
+              "nm" : "Rectangle 1 Fill",
+              "mn" : "{efec3e59-c036-4bc7-9655-e43c902e8154}",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "r" : 1
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "ddd" : 0,
+      "ty" : 4,
+      "ip" : 0.0,
+      "op" : 180.0,
+      "st" : 0,
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100
+        }
+      },
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "nm" : "Rectangle Group",
+          "mn" : "{2101e829-0fd4-4cd3-8220-cd1ef92380c0}",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rectangle 1",
+              "mn" : "{065abe56-76de-4f28-b36d-44c9a39298ae}",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  50.0,
+                  50.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                      20.0,
+                      60.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              }
+            },
+            {
+              "ty" : "fl",
+              "nm" : "Rectangle Fill",
+              "mn" : "{31322740-fb76-4406-bf47-625cc7b2e68f}",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  1.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "r" : 1
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/testsuite/ottie/snapshot/parent-transform.0.node 
b/testsuite/ottie/snapshot/parent-transform.0.node
new file mode 100644
index 0000000000..d8373a01ac
--- /dev/null
+++ b/testsuite/ottie/snapshot/parent-transform.0.node
@@ -0,0 +1,104 @@
+clip {
+  child: container {
+    transform {
+      child: transform {
+        child: transform {
+          child: clip {
+            child: transform {
+              child: container {
+                fill {
+                  child: color {
+                    bounds: -128 -64 256 128;
+                    color: rgb(255,255,0);
+                  }
+                  path: "\
+M -128 -64 h 256 v 128 h -256 z";
+                  fill-rule: winding;
+                }
+                stroke {
+                  child: color {
+                    bounds: -131 -67 262 134;
+                    color: rgb(0,255,0);
+                  }
+                  path: "\
+M -128 -64 h 256 v 128 h -256 z";
+                  line-width: 6;
+                  line-cap: round;
+                  line-join: round;
+                }
+              }
+              transform: translate(128, 128);
+            }
+            clip: 0 0 512 512;
+          }
+          transform: translate(64, 64);
+        }
+        transform: translate(64, 64);
+      }
+      transform: translate(320, 320) rotate(90) scale(1.5) translate(-256, -256);
+    }
+    transform {
+      child: transform {
+        child: clip {
+          child: transform {
+            child: container {
+              fill {
+                child: color {
+                  bounds: -128 -64 256 128;
+                  color: rgb(255,255,0);
+                }
+                path: "\
+M -128 -64 h 256 v 128 h -256 z";
+                fill-rule: winding;
+              }
+              stroke {
+                child: color {
+                  bounds: -131 -67 262 134;
+                  color: rgb(0,255,0);
+                }
+                path: "\
+M -128 -64 h 256 v 128 h -256 z";
+                line-width: 6;
+                line-cap: round;
+                line-join: round;
+              }
+            }
+            transform: translate(128, 128);
+          }
+          clip: 0 0 512 512;
+        }
+        transform: translate(64, 64);
+      }
+      transform: translate(320, 320) rotate(90) scale(1.5) translate(-256, -256);
+    }
+    clip {
+      child: transform {
+        child: container {
+          fill {
+            child: color {
+              bounds: -128 -64 256 128;
+              color: rgb(255,255,0);
+            }
+            path: "\
+M -128 -64 h 256 v 128 h -256 z";
+            fill-rule: winding;
+          }
+          stroke {
+            child: color {
+              bounds: -131 -67 262 134;
+              color: rgb(0,255,0);
+            }
+            path: "\
+M -128 -64 h 256 v 128 h -256 z";
+            line-width: 6;
+            line-cap: round;
+            line-join: round;
+          }
+        }
+        transform: translate(128, 128);
+      }
+      clip: 0 0 512 512;
+    }
+  }
+  clip: 0 0 512 512;
+}
diff --git a/testsuite/ottie/snapshot/parent-transform.lottie.json 
b/testsuite/ottie/snapshot/parent-transform.lottie.json
new file mode 100644
index 0000000000..171a801d3e
--- /dev/null
+++ b/testsuite/ottie/snapshot/parent-transform.lottie.json
@@ -0,0 +1,348 @@
+{
+  "v" : "5.5.2",
+  "ip" : 0.0,
+  "op" : 180.0,
+  "nm" : "Animation",
+  "mn" : "{a8724d85-3a25-41b3-b089-c82978382de4}",
+  "fr" : 60.0,
+  "w" : 512,
+  "h" : 512,
+  "assets" : [
+    {
+      "nm" : "Composition",
+      "mn" : "{8b0d1472-8c27-407b-ab9a-c9373873469c}",
+      "id" : "{8b0d1472-8c27-407b-ab9a-c9373873469c}",
+      "layers" : [
+        {
+          "ddd" : 0,
+          "ty" : 4,
+          "ind" : 5,
+          "st" : 0,
+          "ip" : 0.0,
+          "op" : 180.0,
+          "nm" : "Layer 1",
+          "mn" : "{2eafbf94-5c0e-491b-953d-1fb5cb91f56a}",
+          "ks" : {
+            "a" : {
+              "a" : 0,
+              "k" : [
+                0.0,
+                0.0
+              ]
+            },
+            "p" : {
+              "a" : 0,
+              "k" : [
+                128.0,
+                128.0
+              ]
+            },
+            "s" : {
+              "a" : 0,
+              "k" : [
+                100.0,
+                100.0
+              ]
+            },
+            "r" : {
+              "a" : 0,
+              "k" : 0.0
+            },
+            "o" : {
+              "a" : 0,
+              "k" : 100.0
+            }
+          },
+          "shapes" : [
+            {
+              "ty" : "gr",
+              "nm" : "Yellow 1",
+              "mn" : "{15c56212-2db8-4dee-a721-0803bf36a1d6}",
+              "it" : [
+                {
+                  "ty" : "rc",
+                  "nm" : "Rectangle 1",
+                  "mn" : "{aacda730-7a54-4b3c-b4cd-830d2510149b}",
+                  "p" : {
+                    "a" : 0,
+                    "k" : [
+                      0.0,
+                      0.0
+                    ]
+                  },
+                  "s" : {
+                    "a" : 0,
+                    "k" : [
+                      256.0,
+                      128.0
+                    ]
+                  },
+                  "r" : {
+                    "a" : 0,
+                    "k" : 0.0
+                  }
+                },
+                {
+                  "ty" : "st",
+                  "nm" : "Rectangle Stroke",
+                  "mn" : "{75776bc2-75f1-41f1-afd5-bb6a912e6557}",
+                  "o" : {
+                    "a" : 0,
+                    "k" : 100.0
+                  },
+                  "c" : {
+                    "a" : 0,
+                    "k" : [
+                      0.0,
+                      1.0,
+                      0.0,
+                      1.0
+                    ]
+                  },
+                  "lc" : 2,
+                  "lj" : 2,
+                  "ml" : 4.0,
+                  "w" : {
+                    "a" : 0,
+                    "k" : 6.0
+                  }
+                },
+                {
+                  "ty" : "fl",
+                  "nm" : "Rectangle Fill 1",
+                  "mn" : "{1bcc2824-a27e-4d28-8ecb-54fbd446ac94}",
+                  "o" : {
+                    "a" : 0,
+                    "k" : 100.0
+                  },
+                  "c" : {
+                    "a" : 0,
+                    "k" : [
+                      1.0,
+                      1.0,
+                      0.0,
+                      1.0
+                    ]
+                  },
+                  "r" : 1
+                },
+                {
+                  "ty" : "tr",
+                  "a" : {
+                    "a" : 0,
+                    "k" : [
+                      0.0,
+                      0.0
+                    ]
+                  },
+                  "p" : {
+                    "a" : 0,
+                    "k" : [
+                      0.0,
+                      0.0
+                    ]
+                  },
+                  "s" : {
+                    "a" : 0,
+                    "k" : [
+                      100.0,
+                      100.0
+                    ]
+                  },
+                  "r" : {
+                    "a" : 0,
+                    "k" : 0.0
+                  },
+                  "o" : {
+                    "a" : 0,
+                    "k" : 100.0
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ty" : 3,
+      "ind" : 4,
+      "st" : 0,
+      "ip" : 0.0,
+      "op" : 180.0,
+      "nm" : "Layer",
+      "mn" : "{462230a4-7dce-44e2-961b-c8d340c1fbec}",
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            256.0,
+            256.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            320.0,
+            320.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            150.0,
+            150.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 90.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 40.0
+        }
+      }
+    },
+    {
+      "ty" : 0,
+      "ddd" : 0,
+      "nm" : "Composition Layer 1",
+      "mn" : "{022cabe3-7c64-4c1c-a027-3325b4002875}",
+      "ip" : 0.0,
+      "op" : 180.0,
+      "ind" : 3,
+      "st" : 0.0,
+      "sr" : 1.0,
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100.0
+        }
+      },
+      "refId" : "{8b0d1472-8c27-407b-ab9a-c9373873469c}",
+      "w" : 512.0,
+      "h" : 512.0
+    },
+    {
+      "ty" : 0,
+      "ddd" : 0,
+      "nm" : "Composition Layer",
+      "mn" : "{cf49cd0d-3e46-4faa-b1a7-94d07e2fa966}",
+      "ip" : 0.0,
+      "op" : 180.0,
+      "ind" : 2,
+      "st" : 0.0,
+      "sr" : 1.0,
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            64.0,
+            64.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100.0
+        }
+      },
+      "refId" : "{8b0d1472-8c27-407b-ab9a-c9373873469c}",
+      "w" : 512.0,
+      "h" : 512.0,
+      "parent" : 4
+    },
+    {
+      "ty" : 0,
+      "ddd" : 0,
+      "nm" : "Composition Layer 2",
+      "mn" : "{e906e0b5-3ce7-4047-a80f-18d6109f665c}",
+      "ip" : 0.0,
+      "op" : 180.0,
+      "ind" : 1,
+      "st" : 0.0,
+      "sr" : 1.0,
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            0.0,
+            0.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            64.0,
+            64.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100.0
+        }
+      },
+      "refId" : "{8b0d1472-8c27-407b-ab9a-c9373873469c}",
+      "w" : 512.0,
+      "h" : 512.0,
+      "parent" : 2
+    }
+  ]
+}
diff --git a/testsuite/ottie/snapshot/paths-respect-group-transform.0.node 
b/testsuite/ottie/snapshot/paths-respect-group-transform.0.node
new file mode 100644
index 0000000000..8c0491655a
--- /dev/null
+++ b/testsuite/ottie/snapshot/paths-respect-group-transform.0.node
@@ -0,0 +1,30 @@
+transform {
+  child: container {
+    fill {
+      child: color {
+        bounds: -64 -128 128 256;
+        color: rgb(0,0,255);
+      }
+      path: "\
+M 64 -128\
+L 64 128\
+L -64 128\
+L -64 -128\
+Z";
+      fill-rule: winding;
+    }
+    transform {
+      child: fill {
+        child: color {
+          bounds: -128 -64 256 128;
+          color: rgba(255,0,0,0.4);
+        }
+        path: "\
+M -128 -64 h 256 v 128 h -256 z";
+        fill-rule: winding;
+      }
+      transform: rotate(90);
+    }
+  }
+  transform: translate(256, 256);
+}
diff --git a/testsuite/ottie/snapshot/paths-respect-group-transform.lottie.json 
b/testsuite/ottie/snapshot/paths-respect-group-transform.lottie.json
new file mode 100644
index 0000000000..bcf78b13b6
--- /dev/null
+++ b/testsuite/ottie/snapshot/paths-respect-group-transform.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{e77b27cf-a6b9-4564-9165-c191e8e70c8f}","fr":60.000,"w":512,"h":512,"assets":[],"layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":180.000,"nm":"Layer","mn":"{3bd686e5-3410-4a01-90e1-fcf41716d74c}","ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"gr","nm":"Rectangle
 
Group","mn":"{49eb3094-7a98-4d7e-924b-d4ddda21b7b7}","it":[{"ty":"rc","nm":"Rectangle","mn":"{8504d4f3-72f0-41cd-8fd2-1e3fa4e50d1e}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[256.000,128.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 
Fill","mn":"{c397fe0c-516e-4ea8-977b-9278a3aa967d}","o":{"a":0,"k":40.000},"c":{"a":0,"k":[1.000,0.000,0.000,1.000]},"r":1},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":90.000},"o":{"a":0,"k":100.000}}]},{"ty":"fl","nm":"Re
 ctangle Fill 
1","mn":"{f5b7dac0-2806-4758-aae4-04ee887ff065}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[0.000,0.000,1.000,1.000]},"r":1}]}]}
diff --git a/testsuite/ottie/snapshot/rect-path-order.0.node b/testsuite/ottie/snapshot/rect-path-order.0.node
new file mode 100644
index 0000000000..aa3a4dfe2f
--- /dev/null
+++ b/testsuite/ottie/snapshot/rect-path-order.0.node
@@ -0,0 +1,261 @@
+transform {
+  child: stroke {
+    child: color {
+      bounds: 13 78.5 68.5 20.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 16 80 O 16 96, 32 96, 0.70710676908493042\
+L 79.999984741210938 96";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(384, 384);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 13 29 36.5 52.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 16 80\
+L 16 48 O 16 32, 32 32, 0.70710676908493042\
+L 47.999988555908203 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(256, 384);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 14.5 94.5 83 3;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 16 96\
+L 96 96";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(128, 384);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 14.5 30.5 19 67;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 16 96\
+L 16 32\
+L 32 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(0, 384);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 78.5 46.5 36.5 52.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 79.999984741210938 96\
+L 96 96 O 112 96, 112 80, 0.70710676908493042\
+L 112 48";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(384, 256);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 46.5 29 68.5 20.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 47.999988555908203 32\
+L 96 32 O 112 32, 112 48, 0.70710676908493042";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(256, 256);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 94.5 30.5 19 67;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 96 96\
+L 112 96\
+L 112 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(128, 256);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 30.5 30.5 83 3;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 32 32\
+L 112 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(0, 256);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 13 29 36.5 54;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 48 32\
+L 32 32 O 16 32, 16 48, 0.70710676908493042\
+L 16 80 O 16 80, 16 80, 1";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(384, 128);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 13 78.5 68.5 20.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 79.999992370605469 96\
+L 32 96 O 16 96, 16 80, 0.70710676908493042";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(256, 128);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 14.5 30.5 19 67;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 32 32\
+L 16 32\
+L 16 96";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(128, 128);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 14.5 94.5 83 3;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 96 96\
+L 16 96";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(0, 128);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 46.5 29 68.5 20.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 112 48 O 112 32, 96 32, 0.70710676908493042\
+L 48 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(384, 0);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 78.5 46.5 36.5 52.5;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 112 48\
+L 112 80 O 112 96, 96 96, 0.70710676908493042\
+L 79.999992370605469 96";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(256, 0);
+}
+transform {
+  child: stroke {
+    child: color {
+      bounds: 30.5 30.5 83 3;
+      color: rgb(255,0,0);
+    }
+    path: "\
+M 112 32\
+L 32 32";
+    line-width: 6;
+    line-cap: butt;
+    line-join: miter;
+    miter-limit: 0;
+  }
+  transform: translate(128, 0);
+}
+stroke {
+  child: color {
+    bounds: 94.5 30.5 19 67;
+    color: rgb(255,0,0);
+  }
+  path: "\
+M 112 32\
+L 112 96\
+L 96 96";
+  line-width: 6;
+  line-cap: butt;
+  line-join: miter;
+  miter-limit: 0;
+}
diff --git a/testsuite/ottie/snapshot/rect-path-order.lottie.json 
b/testsuite/ottie/snapshot/rect-path-order.lottie.json
new file mode 100644
index 0000000000..fa89e70143
--- /dev/null
+++ b/testsuite/ottie/snapshot/rect-path-order.lottie.json
@@ -0,0 +1,1816 @@
+{
+  "v" : "5.5.2",
+  "ip" : 0.0,
+  "op" : 180.0,
+  "nm" : "Animation",
+  "mn" : "{7153872e-1744-4216-afbb-03b46b40fd05}",
+  "fr" : 60.0,
+  "w" : 512,
+  "h" : 512,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ty" : 4,
+      "ind" : 0,
+      "st" : 0,
+      "ip" : 0.0,
+      "op" : 180.0,
+      "nm" : "Layer",
+      "mn" : "{cd0e6ac2-2d03-42dd-aa7d-033d609a938e}",
+      "ks" : {
+        "a" : {
+          "a" : 0,
+          "k" : [
+            256.0,
+            256.0
+          ]
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            256.0,
+            256.0
+          ]
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100.0,
+            100.0
+          ]
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0.0
+        },
+        "o" : {
+          "a" : 0,
+          "k" : 100.0
+        }
+      },
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "nm" : "Group Forwards",
+          "mn" : "Group-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Forwards",
+              "mn" : "Rect-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Forwards",
+              "mn" : "Trim-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Forwards",
+              "mn" : "Stroke-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Backwards",
+          "mn" : "Group-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Backwards",
+              "mn" : "Rect-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Backwards",
+              "mn" : "Trim-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Backwards",
+              "mn" : "Stroke-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  128.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded Forwards",
+          "mn" : "Group-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded Forwards",
+              "mn" : "Rect-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded Forwards",
+              "mn" : "Trim-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded Forwards",
+              "mn" : "Stroke-Rounded-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  256.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded Backwards",
+          "mn" : "Group-Rounded-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded Backwards",
+              "mn" : "Rect-Rounded-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded Backwards",
+              "mn" : "Trim-Rounded-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded Backwards",
+              "mn" : "Stroke-Rounded-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  384.0,
+                  0.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Offset Forwards",
+          "mn" : "Group-Offset-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Offset Forwards",
+              "mn" : "Rect-Offset-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Offset Forwards",
+              "mn" : "Trim-Offset-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Offset Forwards",
+              "mn" : "Stroke-Offset-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  128.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Backwards",
+          "mn" : "Group-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Backwards",
+              "mn" : "Rect-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Backwards",
+              "mn" : "Trim-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Backwards",
+              "mn" : "Stroke-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  128.0,
+                  128.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded Offset Forwards",
+          "mn" : "Group-Offset-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded Offset Forwards",
+              "mn" : "Rect-Offset-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded Offset Forwards",
+              "mn" : "Trim-Offset-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded Offset Forwards",
+              "mn" : "Stroke-Rounded-Offset-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  256.0,
+                  128.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded Backwards",
+          "mn" : "Group-Rounded-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded Backwards",
+              "mn" : "Rect-Rounded-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 25,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded Backwards",
+              "mn" : "Trim-Rounded-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded Backwards",
+              "mn" : "Stroke-Rounded-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  384.0,
+                  128.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group End Forwards",
+          "mn" : "Group-End-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect End Forwards",
+              "mn" : "Rect-End-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim End Forwards",
+              "mn" : "Trim-End-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke End Forwards",
+              "mn" : "Stroke-End-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  256.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group End Backwards",
+          "mn" : "Group-End-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect End Backwards",
+              "mn" : "Rect-End-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim End Backwards",
+              "mn" : "Trim-End-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke End Backwards",
+              "mn" : "Stroke-End-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  128.0,
+                  256.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded End Forwards",
+          "mn" : "Group-End-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded End Forwards",
+              "mn" : "Rect-End-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded End Forwards",
+              "mn" : "Trim-End-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded End Forwards",
+              "mn" : "Stroke-Rounded-End-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  256.0,
+                  256.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded End Backwards",
+          "mn" : "Group-Rounded-End-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded End Backwards",
+              "mn" : "Rect-Rounded-End-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded End Backwards",
+              "mn" : "Trim-Rounded-End-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded End Backwards",
+              "mn" : "Stroke-Rounded-End-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  384.0,
+                  256.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Offset End Forwards",
+          "mn" : "Group-Offset-End-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Offset End Forwards",
+              "mn" : "Rect-Offset-End-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : -90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Offset End Forwards",
+              "mn" : "Trim-Offset-End-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Offset End Forwards",
+              "mn" : "Stroke-Offset-End-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  384.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group End Backwards",
+          "mn" : "Group-End-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect End Backwards",
+              "mn" : "Rect-End-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : -90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim End Backwards",
+              "mn" : "Trim-End-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke End Backwards",
+              "mn" : "Stroke-End-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  128.0,
+                  384.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded Offset End Forwards",
+          "mn" : "Group-Offset-End-Forwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded Offset End Forwards",
+              "mn" : "Rect-Offset-End-Forwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 1
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : -90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded Offset End Forwards",
+              "mn" : "Trim-Offset-End-Forwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded Offset End Forwards",
+              "mn" : "Stroke-Rounded-Offset-End-Forwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  256.0,
+                  384.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        },
+        {
+          "ty" : "gr",
+          "nm" : "Group Rounded End Backwards",
+          "mn" : "Group-Rounded-End-Backwards",
+          "it" : [
+            {
+              "ty" : "rc",
+              "nm" : "Rect Rounded End Backwards",
+              "mn" : "Rect-Rounded-End-Backwards",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  64.0,
+                  64.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  96.0,
+                  64.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 16.0
+              },
+              "d" : 0
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 75,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : -90,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Rounded End Backwards",
+              "mn" : "Trim-Rounded-End-Backwards"
+            },
+            {
+              "ty" : "st",
+              "nm" : "Stroke Rounded End Backwards",
+              "mn" : "Stroke-Rounded-End-Backwards",
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              },
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  1.0,
+                  0.0,
+                  0.0,
+                  1.0
+                ]
+              },
+              "lc" : 1,
+              "lj" : 1,
+              "ml" : 0.0,
+              "w" : {
+                "a" : 0,
+                "k" : 6.0
+              }
+            },
+            {
+              "ty" : "tr",
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0.0,
+                  0.0
+                ]
+              },
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  384.0,
+                  384.0
+                ]
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100.0,
+                  100.0
+                ]
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0.0
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100.0
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.0.node 
b/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.0.node
new file mode 100644
index 0000000000..a88e67ee39
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.0.node
@@ -0,0 +1,16 @@
+clip {
+  child: stroke {
+    child: color {
+      bounds: -30 0 160 100;
+      color: rgb(0,255,0);
+    }
+    path: "\
+M 20 50\
+C 40 50, 60 50, 80 50";
+    line-width: 10;
+    line-cap: square;
+    line-join: miter;
+    miter-limit: 10;
+  }
+  clip: 0 0 100 100;
+}
diff --git a/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.lottie.json 
b/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.lottie.json
new file mode 100644
index 0000000000..ecd4718832
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-0-to-100-shows-everything.lottie.json
@@ -0,0 +1,222 @@
+{
+  "v" : "5.1.8",
+  "fr" : 2,
+  "ip" : 0,
+  "op" : 60,
+  "w" : 100,
+  "h" : 100,
+  "nm" : "Spinner",
+  "ddd" : 0,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ind" : 1,
+      "ty" : 4,
+      "nm" : "spinner Outlines",
+      "sr" : 1,
+      "ks" : {
+        "o" : {
+          "a" : 0,
+          "k" : 100,
+          "ix" : 11
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0,
+          "ix" : 10
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 2
+        },
+        "a" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 1
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100,
+            100,
+            100
+          ],
+          "ix" : 6
+        }
+      },
+      "ao" : 0,
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "it" : [
+            {
+              "ind" : 0,
+              "ty" : "sh",
+              "ix" : 1,
+              "ks" : {
+                "a" : 0,
+                "k" : {
+                  "i" : [
+                    [
+                      -20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "o" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      20,
+                      0
+                    ]
+                  ],
+                  "v" : [
+                    [
+                      20,
+                      50
+                    ],
+                    [
+                      80,
+                      50
+                    ]
+                  ],
+                  "c" : false
+                },
+                "ix" : 2
+              },
+              "nm" : "Path 1",
+              "mn" : "ADBE Vector Shape - Group",
+              "hd" : false
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k": 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Paths 1",
+              "mn" : "ADBE Vector Filter - Trim",
+              "hd" : false
+            },
+            {
+              "ty" : "st",
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  1,
+                  0
+                ],
+                "ix" : 3
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 4
+              },
+              "w" : {
+                "a" : 0,
+                "k" : 10,
+                "ix" : 5
+              },
+              "lc" : 3,
+              "lj" : 1,
+              "ml" : 10,
+              "nm" : "Stroke 1",
+              "mn" : "ADBE Vector Graphic - Stroke",
+              "hd" : false
+            },
+            {
+              "ty" : "tr",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 2
+              },
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 1
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100,
+                  100
+                ],
+                "ix" : 3
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 6
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 7
+              },
+              "sk" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 4
+              },
+              "sa" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 5
+              },
+              "nm" : "Transform"
+            }
+          ],
+          "nm" : "Group 1",
+          "np" : 3,
+          "cix" : 2,
+          "ix" : 1,
+          "mn" : "ADBE Vector Group",
+          "hd" : false
+        }
+      ],
+      "ip" : 0,
+      "op" : 60.0000024438501,
+      "st" : 0,
+      "bm" : 0
+    }
+  ],
+  "markers" : []
+}
diff --git a/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.0.node 
b/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.0.node
new file mode 100644
index 0000000000..1372937793
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.0.node
@@ -0,0 +1,16 @@
+clip {
+  child: stroke {
+    child: color {
+      bounds: -30 0 160 100;
+      color: rgba(0,255,0,0.4);
+    }
+    path: "\
+M 20 50\
+C 40 50, 60 50, 80 50";
+    line-width: 10;
+    line-cap: square;
+    line-join: miter;
+    miter-limit: 10;
+  }
+  clip: 0 0 100 100;
+}
diff --git a/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.lottie.json 
b/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.lottie.json
new file mode 100644
index 0000000000..506b5778e2
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-0-to-200-shows-everything-once.lottie.json
@@ -0,0 +1,222 @@
+{
+  "v" : "5.1.8",
+  "fr" : 2,
+  "ip" : 0,
+  "op" : 60,
+  "w" : 100,
+  "h" : 100,
+  "nm" : "Spinner",
+  "ddd" : 0,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ind" : 1,
+      "ty" : 4,
+      "nm" : "spinner Outlines",
+      "sr" : 1,
+      "ks" : {
+        "o" : {
+          "a" : 0,
+          "k" : 100,
+          "ix" : 11
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0,
+          "ix" : 10
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 2
+        },
+        "a" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 1
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100,
+            100,
+            100
+          ],
+          "ix" : 6
+        }
+      },
+      "ao" : 0,
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "it" : [
+            {
+              "ind" : 0,
+              "ty" : "sh",
+              "ix" : 1,
+              "ks" : {
+                "a" : 0,
+                "k" : {
+                  "i" : [
+                    [
+                      -20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "o" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      20,
+                      0
+                    ]
+                  ],
+                  "v" : [
+                    [
+                      20,
+                      50
+                    ],
+                    [
+                      80,
+                      50
+                    ]
+                  ],
+                  "c" : false
+                },
+                "ix" : 2
+              },
+              "nm" : "Path 1",
+              "mn" : "ADBE Vector Shape - Group",
+              "hd" : false
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k": 100,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Paths 1",
+              "mn" : "ADBE Vector Filter - Trim",
+              "hd" : false
+            },
+            {
+              "ty" : "st",
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  1,
+                  0
+                ],
+                "ix" : 3
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 40,
+                "ix" : 4
+              },
+              "w" : {
+                "a" : 0,
+                "k" : 10,
+                "ix" : 5
+              },
+              "lc" : 3,
+              "lj" : 1,
+              "ml" : 10,
+              "nm" : "Stroke 1",
+              "mn" : "ADBE Vector Graphic - Stroke",
+              "hd" : false
+            },
+            {
+              "ty" : "tr",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 2
+              },
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 1
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100,
+                  100
+                ],
+                "ix" : 3
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 6
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 7
+              },
+              "sk" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 4
+              },
+              "sa" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 5
+              },
+              "nm" : "Transform"
+            }
+          ],
+          "nm" : "Group 1",
+          "np" : 3,
+          "cix" : 2,
+          "ix" : 1,
+          "mn" : "ADBE Vector Group",
+          "hd" : false
+        }
+      ],
+      "ip" : 0,
+      "op" : 60.0000024438501,
+      "st" : 0,
+      "bm" : 0
+    }
+  ],
+  "markers" : []
+}
diff --git a/testsuite/ottie/snapshot/trim-equal-is-empty.0.node 
b/testsuite/ottie/snapshot/trim-equal-is-empty.0.node
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/testsuite/ottie/snapshot/trim-equal-is-empty.lottie.json 
b/testsuite/ottie/snapshot/trim-equal-is-empty.lottie.json
new file mode 100644
index 0000000000..c4cb56c80a
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-equal-is-empty.lottie.json
@@ -0,0 +1,247 @@
+{
+  "v" : "5.1.8",
+  "fr" : 2,
+  "ip" : 0,
+  "op" : 60,
+  "w" : 100,
+  "h" : 100,
+  "nm" : "Spinner",
+  "ddd" : 0,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ind" : 1,
+      "ty" : 4,
+      "nm" : "spinner Outlines",
+      "sr" : 1,
+      "ks" : {
+        "o" : {
+          "a" : 0,
+          "k" : 100,
+          "ix" : 11
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0,
+          "ix" : 10
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 2
+        },
+        "a" : {
+          "a" : 0,
+          "k" : [
+            160,
+            284,
+            0
+          ],
+          "ix" : 1
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100,
+            100,
+            100
+          ],
+          "ix" : 6
+        }
+      },
+      "ao" : 0,
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "it" : [
+            {
+              "ind" : 0,
+              "ty" : "sh",
+              "ix" : 1,
+              "ks" : {
+                "a" : 0,
+                "k" : {
+                  "i" : [
+                    [
+                      0,
+                      19.882000000000001
+                    ],
+                    [
+                      19.882000000000001,
+                      0
+                    ],
+                    [
+                      0,
+                      -19.882000000000001
+                    ],
+                    [
+                      -19.882000000000001,
+                      0
+                    ]
+                  ],
+                  "o" : [
+                    [
+                      0,
+                      -19.882000000000001
+                    ],
+                    [
+                      -19.882000000000001,
+                      0
+                    ],
+                    [
+                      0,
+                      19.882000000000001
+                    ],
+                    [
+                      19.882000000000001,
+                      0
+                    ]
+                  ],
+                  "v" : [
+                    [
+                      36,
+                      0
+                    ],
+                    [
+                      0,
+                      -36
+                    ],
+                    [
+                      -36,
+                      0
+                    ],
+                    [
+                      0,
+                      36
+                    ]
+                  ],
+                  "c" : true
+                },
+                "ix" : 2
+              },
+              "nm" : "Path 1",
+              "mn" : "ADBE Vector Shape - Group",
+              "hd" : false
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 90,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k": 90,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Paths 1",
+              "mn" : "ADBE Vector Filter - Trim",
+              "hd" : false
+            },
+            {
+              "ty" : "st",
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  1,
+                  0,
+                  1
+                ],
+                "ix" : 3
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 4
+              },
+              "w" : {
+                "a" : 0,
+                "k" : 10,
+                "ix" : 5
+              },
+              "lc" : 3,
+              "lj" : 1,
+              "ml" : 10,
+              "nm" : "Stroke 1",
+              "mn" : "ADBE Vector Graphic - Stroke",
+              "hd" : false
+            },
+            {
+              "ty" : "tr",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  160,
+                  284
+                ],
+                "ix" : 2
+              },
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 1
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100,
+                  100
+                ],
+                "ix" : 3
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 6
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 7
+              },
+              "sk" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 4
+              },
+              "sa" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 5
+              },
+              "nm" : "Transform"
+            }
+          ],
+          "nm" : "Group 1",
+          "np" : 3,
+          "cix" : 2,
+          "ix" : 1,
+          "mn" : "ADBE Vector Group",
+          "hd" : false
+        }
+      ],
+      "ip" : 0,
+      "op" : 60.0000024438501,
+      "st" : 0,
+      "bm" : 0
+    }
+  ],
+  "markers" : []
+}
diff --git a/testsuite/ottie/snapshot/trim-offset-rotates.0.node 
b/testsuite/ottie/snapshot/trim-offset-rotates.0.node
new file mode 100644
index 0000000000..31d3889d14
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-offset-rotates.0.node
@@ -0,0 +1,18 @@
+clip {
+  child: stroke {
+    child: color {
+      bounds: -30 0 160 100;
+      color: rgb(0,255,0);
+    }
+    path: "\
+M 77 50\
+C 78 50, 79 50, 80 50\
+M 20 50\
+C 21 50, 22 50, 23 50";
+    line-width: 10;
+    line-cap: square;
+    line-join: miter;
+    miter-limit: 10;
+  }
+  clip: 0 0 100 100;
+}
diff --git a/testsuite/ottie/snapshot/trim-offset-rotates.lottie.json 
b/testsuite/ottie/snapshot/trim-offset-rotates.lottie.json
new file mode 100644
index 0000000000..a669546728
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-offset-rotates.lottie.json
@@ -0,0 +1,222 @@
+{
+  "v" : "5.1.8",
+  "fr" : 2,
+  "ip" : 0,
+  "op" : 60,
+  "w" : 100,
+  "h" : 100,
+  "nm" : "Spinner",
+  "ddd" : 0,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ind" : 1,
+      "ty" : 4,
+      "nm" : "spinner Outlines",
+      "sr" : 1,
+      "ks" : {
+        "o" : {
+          "a" : 0,
+          "k" : 100,
+          "ix" : 11
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0,
+          "ix" : 10
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 2
+        },
+        "a" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 1
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100,
+            100,
+            100
+          ],
+          "ix" : 6
+        }
+      },
+      "ao" : 0,
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "it" : [
+            {
+              "ind" : 0,
+              "ty" : "sh",
+              "ix" : 1,
+              "ks" : {
+                "a" : 0,
+                "k" : {
+                  "i" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "o" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "v" : [
+                    [
+                      20,
+                      50
+                    ],
+                    [
+                      80,
+                      50
+                    ]
+                  ],
+                  "c" : false
+                },
+                "ix" : 2
+              },
+              "nm" : "Path 1",
+              "mn" : "ADBE Vector Shape - Group",
+              "hd" : false
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 45,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k": 55,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 180,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Paths 1",
+              "mn" : "ADBE Vector Filter - Trim",
+              "hd" : false
+            },
+            {
+              "ty" : "st",
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  1,
+                  0
+                ],
+                "ix" : 3
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 4
+              },
+              "w" : {
+                "a" : 0,
+                "k" : 10,
+                "ix" : 5
+              },
+              "lc" : 3,
+              "lj" : 1,
+              "ml" : 10,
+              "nm" : "Stroke 1",
+              "mn" : "ADBE Vector Graphic - Stroke",
+              "hd" : false
+            },
+            {
+              "ty" : "tr",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 2
+              },
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 1
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100,
+                  100
+                ],
+                "ix" : 3
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 6
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 7
+              },
+              "sk" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 4
+              },
+              "sa" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 5
+              },
+              "nm" : "Transform"
+            }
+          ],
+          "nm" : "Group 1",
+          "np" : 3,
+          "cix" : 2,
+          "ix" : 1,
+          "mn" : "ADBE Vector Group",
+          "hd" : false
+        }
+      ],
+      "ip" : 0,
+      "op" : 60.0000024438501,
+      "st" : 0,
+      "bm" : 0
+    }
+  ],
+  "markers" : []
+}
diff --git a/testsuite/ottie/snapshot/trim-startend-does-minmax.0.node 
b/testsuite/ottie/snapshot/trim-startend-does-minmax.0.node
new file mode 100644
index 0000000000..15b1d8b973
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-startend-does-minmax.0.node
@@ -0,0 +1,16 @@
+clip {
+  child: stroke {
+    child: color {
+      bounds: -3 0 106 100;
+      color: rgb(0,255,0);
+    }
+    path: "\
+M 47 50\
+C 49 50, 51 50, 53 50";
+    line-width: 10;
+    line-cap: square;
+    line-join: miter;
+    miter-limit: 10;
+  }
+  clip: 0 0 100 100;
+}
diff --git a/testsuite/ottie/snapshot/trim-startend-does-minmax.lottie.json 
b/testsuite/ottie/snapshot/trim-startend-does-minmax.lottie.json
new file mode 100644
index 0000000000..cdf1a965d9
--- /dev/null
+++ b/testsuite/ottie/snapshot/trim-startend-does-minmax.lottie.json
@@ -0,0 +1,222 @@
+{
+  "v" : "5.1.8",
+  "fr" : 2,
+  "ip" : 0,
+  "op" : 60,
+  "w" : 100,
+  "h" : 100,
+  "nm" : "Spinner",
+  "ddd" : 0,
+  "assets" : [],
+  "layers" : [
+    {
+      "ddd" : 0,
+      "ind" : 1,
+      "ty" : 4,
+      "nm" : "spinner Outlines",
+      "sr" : 1,
+      "ks" : {
+        "o" : {
+          "a" : 0,
+          "k" : 100,
+          "ix" : 11
+        },
+        "r" : {
+          "a" : 0,
+          "k" : 0,
+          "ix" : 10
+        },
+        "p" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 2
+        },
+        "a" : {
+          "a" : 0,
+          "k" : [
+            50,
+            50,
+            0
+          ],
+          "ix" : 1
+        },
+        "s" : {
+          "a" : 0,
+          "k" : [
+            100,
+            100,
+            100
+          ],
+          "ix" : 6
+        }
+      },
+      "ao" : 0,
+      "shapes" : [
+        {
+          "ty" : "gr",
+          "it" : [
+            {
+              "ind" : 0,
+              "ty" : "sh",
+              "ix" : 1,
+              "ks" : {
+                "a" : 0,
+                "k" : {
+                  "i" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "o" : [
+                    [
+                      20,
+                      0
+                    ],
+                    [
+                      -20,
+                      0
+                    ]
+                  ],
+                  "v" : [
+                    [
+                      20,
+                      50
+                    ],
+                    [
+                      80,
+                      50
+                    ]
+                  ],
+                  "c" : false
+                },
+                "ix" : 2
+              },
+              "nm" : "Path 1",
+              "mn" : "ADBE Vector Shape - Group",
+              "hd" : false
+            },
+            {
+              "ty" : "tm",
+              "s" : {
+                "a" : 0,
+                "k" : 45,
+                "ix" : 1
+              },
+              "e" : {
+                "a" : 0,
+                "k": 55,
+                "ix" : 2
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 3
+              },
+              "m" : 1,
+              "ix" : 2,
+              "nm" : "Trim Paths 1",
+              "mn" : "ADBE Vector Filter - Trim",
+              "hd" : false
+            },
+            {
+              "ty" : "st",
+              "c" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  1,
+                  0
+                ],
+                "ix" : 3
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 4
+              },
+              "w" : {
+                "a" : 0,
+                "k" : 10,
+                "ix" : 5
+              },
+              "lc" : 3,
+              "lj" : 1,
+              "ml" : 10,
+              "nm" : "Stroke 1",
+              "mn" : "ADBE Vector Graphic - Stroke",
+              "hd" : false
+            },
+            {
+              "ty" : "tr",
+              "p" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 2
+              },
+              "a" : {
+                "a" : 0,
+                "k" : [
+                  0,
+                  0
+                ],
+                "ix" : 1
+              },
+              "s" : {
+                "a" : 0,
+                "k" : [
+                  100,
+                  100
+                ],
+                "ix" : 3
+              },
+              "r" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 6
+              },
+              "o" : {
+                "a" : 0,
+                "k" : 100,
+                "ix" : 7
+              },
+              "sk" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 4
+              },
+              "sa" : {
+                "a" : 0,
+                "k" : 0,
+                "ix" : 5
+              },
+              "nm" : "Transform"
+            }
+          ],
+          "nm" : "Group 1",
+          "np" : 3,
+          "cix" : 2,
+          "ix" : 1,
+          "mn" : "ADBE Vector Group",
+          "hd" : false
+        }
+      ],
+      "ip" : 0,
+      "op" : 60.0000024438501,
+      "st" : 0,
+      "bm" : 0
+    }
+  ],
+  "markers" : []
+}
diff --git a/testsuite/ottie/snapshot/two-shapes.0.node b/testsuite/ottie/snapshot/two-shapes.0.node
new file mode 100644
index 0000000000..7e02113f3d
--- /dev/null
+++ b/testsuite/ottie/snapshot/two-shapes.0.node
@@ -0,0 +1,27 @@
+transform {
+  child: container {
+    stroke {
+      child: color {
+        bounds: -153 -153 306 306;
+        color: rgb(255,255,255);
+      }
+      path: "\
+M -50 -150 h 100 v 300 h -100 z\
+M -150 -50 h 300 v 100 h -300 z";
+      line-width: 6;
+      line-cap: round;
+      line-join: round;
+    }
+    fill {
+      child: color {
+        bounds: -150 -150 300 300;
+        color: rgba(255,0,0,0.4);
+      }
+      path: "\
+M -50 -150 h 100 v 300 h -100 z\
+M -150 -50 h 300 v 100 h -300 z";
+      fill-rule: winding;
+    }
+  }
+  transform: translate(256, 256);
+}
diff --git a/testsuite/ottie/snapshot/two-shapes.lottie.json b/testsuite/ottie/snapshot/two-shapes.lottie.json
new file mode 100644
index 0000000000..8b9b0f018f
--- /dev/null
+++ b/testsuite/ottie/snapshot/two-shapes.lottie.json
@@ -0,0 +1 @@
+{"v":"5.5.2","ip":0.000,"op":180.000,"nm":"Animation","mn":"{87fa173e-bf45-44b2-ada5-fb39a7fbb6ee}","fr":60.000,"w":512,"h":512,"assets":[],"layers":[{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0.000,"op":180.000,"nm":"Layer","mn":"{956d0e46-fdae-4303-ba42-8a0e78c5d812}","ks":{"a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[256.000,256.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}},"shapes":[{"ty":"gr","nm":"Rectangle
 
Group","mn":"{6204aa15-606b-4735-9ab7-d6364fd913aa}","it":[{"ty":"rc","nm":"Rectangle","mn":"{119a0c41-bc85-422b-a83d-5795fda9753b}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,300.000]},"r":{"a":0,"k":0.000}},{"ty":"rc","nm":"Rectangle
 
1","mn":"{4cb25c34-b565-494d-ac17-dfb224b793f6}","p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[300.000,100.000]},"r":{"a":0,"k":0.000}},{"ty":"fl","nm":"Rectangle
 
Fill","mn":"{e2f5d06c-1170-448a-b325-61ad8c4d94d5}","o":{"a":0,"k":40.000},"c":{"a":0,"k":[1.000,0.000,0.000,1.000]},"r":1},{"ty":"st",
 "nm":"Ellipse 
Stroke","mn":"{1db4727e-dec1-43aa-abf2-8603df97c26d}","o":{"a":0,"k":100.000},"c":{"a":0,"k":[1.000,1.000,1.000,1.000]},"lc":2,"lj":2,"ml":4.000,"w":{"a":0,"k":6.000}},{"ty":"tr","a":{"a":0,"k":[0.000,0.000]},"p":{"a":0,"k":[0.000,0.000]},"s":{"a":0,"k":[100.000,100.000]},"r":{"a":0,"k":0.000},"o":{"a":0,"k":100.000}}]}]}]}
\ No newline at end of file


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]