Added support for hidden layers ("hd" property) (#1024)

diff --git a/LottieSample/src/main/assets/Tests/hd.json b/LottieSample/src/main/assets/Tests/hd.json
new file mode 100644
index 0000000..512ec03
--- /dev/null
+++ b/LottieSample/src/main/assets/Tests/hd.json
@@ -0,0 +1,151 @@
+{
+    "v": "5.3.4",
+    "fr": 30.0000305175781,
+    "ip": 0,
+    "op": 30.0000305175781,
+    "w": 300,
+    "h": 300,
+    "nm": "Comp 1",
+    "ddd": 0,
+    "assets": [],
+    "layers": [
+        {
+            "ddd": 0,
+            "ind": 1,
+            "ty": 4,
+            "nm": "Shape Layer 1",
+            "sr": 1,
+            "ks": {
+                "o": {
+                    "a": 0,
+                    "k": 100,
+                    "ix": 11
+                },
+                "r": {
+                    "a": 0,
+                    "k": 0,
+                    "ix": 10
+                },
+                "p": {
+                    "a": 0,
+                    "k": [
+                        150,
+                        150,
+                        0
+                    ],
+                    "ix": 2
+                },
+                "a": {
+                    "a": 0,
+                    "k": [
+                        0,
+                        0,
+                        0
+                    ],
+                    "ix": 1
+                },
+                "s": {
+                    "a": 0,
+                    "k": [
+                        100,
+                        100,
+                        100
+                    ],
+                    "ix": 6
+                }
+            },
+            "ao": 0,
+            "shapes": [
+                {
+                    "ty": "rc",
+                    "d": 1,
+                    "s": {
+                        "a": 0,
+                        "k": [
+                            200,
+                            200
+                        ],
+                        "ix": 2
+                    },
+                    "p": {
+                        "a": 0,
+                        "k": [
+                            0,
+                            0
+                        ],
+                        "ix": 3
+                    },
+                    "r": {
+                        "a": 0,
+                        "k": 0,
+                        "ix": 4
+                    },
+                    "nm": "Rectangle Path 1",
+                    "mn": "ADBE Vector Shape - Rect",
+                    "hd": false
+                },
+                {
+                    "ty": "st",
+                    "c": {
+                        "a": 0,
+                        "k": [
+                            0,
+                            0.104963175952,
+                            1,
+                            1
+                        ],
+                        "ix": 3
+                    },
+                    "o": {
+                        "a": 0,
+                        "k": 100,
+                        "ix": 4
+                    },
+                    "w": {
+                        "a": 0,
+                        "k": 35,
+                        "ix": 5
+                    },
+                    "lc": 1,
+                    "lj": 1,
+                    "ml": 4,
+                    "ml2": {
+                        "a": 0,
+                        "k": 4,
+                        "ix": 8
+                    },
+                    "nm": "Stroke 1",
+                    "mn": "ADBE Vector Graphic - Stroke",
+                    "hd": false
+                },
+                {
+                    "ty": "fl",
+                    "c": {
+                        "a": 0,
+                        "k": [
+                            1,
+                            0,
+                            0,
+                            1
+                        ],
+                        "ix": 4
+                    },
+                    "o": {
+                        "a": 0,
+                        "k": 100,
+                        "ix": 5
+                    },
+                    "r": 1,
+                    "nm": "Fill 1",
+                    "mn": "ADBE Vector Graphic - Fill",
+                    "hd": true
+                }
+            ],
+            "ip": 0,
+            "op": 30.0000305175781,
+            "st": 0,
+            "bm": 0
+        }
+    ],
+    "markers": []
+}
\ No newline at end of file
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
index 306c96f..81c06c6 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
@@ -50,6 +50,7 @@
   private final RectF rect = new RectF();
 
   private final String name;
+  private final boolean hidden;
   private final List<Content> contents;
   private final LottieDrawable lottieDrawable;
   @Nullable private List<PathContent> pathContents;
@@ -57,14 +58,15 @@
 
   public ContentGroup(final LottieDrawable lottieDrawable, BaseLayer layer, ShapeGroup shapeGroup) {
     this(lottieDrawable, layer, shapeGroup.getName(),
-        contentsFromModels(lottieDrawable, layer, shapeGroup.getItems()),
+            shapeGroup.isHidden(), contentsFromModels(lottieDrawable, layer, shapeGroup.getItems()),
         findTransform(shapeGroup.getItems()));
   }
 
   ContentGroup(final LottieDrawable lottieDrawable, BaseLayer layer,
-      String name, List<Content> contents, @Nullable AnimatableTransform transform) {
+               String name, boolean hidden, List<Content> contents, @Nullable AnimatableTransform transform) {
     this.name = name;
     this.lottieDrawable = lottieDrawable;
+    this.hidden = hidden;
     this.contents = contents;
 
     if (transform != null) {
@@ -134,6 +136,9 @@
       matrix.set(transformAnimation.getMatrix());
     }
     path.reset();
+    if (hidden) {
+      return path;
+    }
     for (int i = contents.size() - 1; i >= 0; i--) {
       Content content = contents.get(i);
       if (content instanceof PathContent) {
@@ -144,6 +149,9 @@
   }
 
   @Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
+    if (hidden) {
+      return;
+    }
     matrix.set(parentMatrix);
     int alpha;
     if (transformAnimation != null) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/EllipseContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/EllipseContent.java
index dbc4ffb..21e08e3 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/EllipseContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/EllipseContent.java
@@ -77,6 +77,10 @@
 
     path.reset();
 
+    if (circleShape.isHidden()) {
+      isPathValid = true;
+      return path;
+    }
 
     PointF size = sizeAnimation.getValue();
     float halfWidth = size.x / 2f;
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
index 8312b56..cb4d3d1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
@@ -30,6 +30,7 @@
   private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
   private final BaseLayer layer;
   private final String name;
+  private final boolean hidden;
   private final List<PathContent> paths = new ArrayList<>();
   private final BaseKeyframeAnimation<Integer, Integer> colorAnimation;
   private final BaseKeyframeAnimation<Integer, Integer> opacityAnimation;
@@ -39,6 +40,7 @@
   public FillContent(final LottieDrawable lottieDrawable, BaseLayer layer, ShapeFill fill) {
     this.layer = layer;
     name = fill.getName();
+    hidden = fill.isHidden();
     this.lottieDrawable = lottieDrawable;
     if (fill.getColor() == null || fill.getOpacity() == null ) {
       colorAnimation = null;
@@ -74,6 +76,9 @@
   }
 
   @Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
+    if (hidden) {
+      return;
+    }
     L.beginSection("FillContent#draw");
     paint.setColor(colorAnimation.getValue());
     int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255);
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index 58f4afb..2245618 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -39,6 +39,7 @@
    */
   private static final int CACHE_STEPS_MS = 32;
   @NonNull private final String name;
+  private final boolean hidden;
   private final BaseLayer layer;
   private final LongSparseArray<LinearGradient> linearGradientCache = new LongSparseArray<>();
   private final LongSparseArray<RadialGradient> radialGradientCache = new LongSparseArray<>();
@@ -59,6 +60,7 @@
   public GradientFillContent(final LottieDrawable lottieDrawable, BaseLayer layer, GradientFill fill) {
     this.layer = layer;
     name = fill.getName();
+    hidden = fill.isHidden();
     this.lottieDrawable = lottieDrawable;
     type = fill.getGradientType();
     path.setFillType(fill.getFillType());
@@ -95,6 +97,9 @@
   }
 
   @Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
+    if (hidden) {
+      return;
+    }
     L.beginSection("GradientFillContent#draw");
     path.reset();
     for (int i = 0; i < paths.size(); i++) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
index 29aa65e..25109d9 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
@@ -23,6 +23,7 @@
   private static final int CACHE_STEPS_MS = 32;
 
   private final String name;
+  private final boolean hidden;
   private final LongSparseArray<LinearGradient> linearGradientCache = new LongSparseArray<>();
   private final LongSparseArray<RadialGradient> radialGradientCache = new LongSparseArray<>();
   private final RectF boundsRect = new RectF();
@@ -41,6 +42,7 @@
 
     name = stroke.getName();
     type = stroke.getGradientType();
+    hidden = stroke.isHidden();
     cacheSteps = (int) (lottieDrawable.getComposition().getDuration() / CACHE_STEPS_MS);
 
     colorAnimation = stroke.getGradientColor().createAnimation();
@@ -57,6 +59,9 @@
   }
 
   @Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
+    if (hidden) {
+      return;
+    }
     getBounds(boundsRect, parentMatrix);
     if (type == GradientType.Linear) {
       paint.setShader(getLinearGradient());
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/MergePathsContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/MergePathsContent.java
index e8cad4a..7acd3ca 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/MergePathsContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/MergePathsContent.java
@@ -50,6 +50,10 @@
   @Override public Path getPath() {
     path.reset();
 
+    if (mergePaths.isHidden()) {
+      return path;
+    }
+
     switch (mergePaths.getMode()) {
       case Merge:
         addPaths();
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
index a204e41..86f0dd5 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/PolystarContent.java
@@ -32,6 +32,7 @@
   private final String name;
   private final LottieDrawable lottieDrawable;
   private final PolystarShape.Type type;
+  private final boolean hidden;
   private final BaseKeyframeAnimation<?, Float> pointsAnimation;
   private final BaseKeyframeAnimation<?, PointF> positionAnimation;
   private final BaseKeyframeAnimation<?, Float> rotationAnimation;
@@ -49,6 +50,7 @@
 
     name = polystarShape.getName();
     type = polystarShape.getType();
+    hidden = polystarShape.isHidden();
     pointsAnimation = polystarShape.getPoints().createAnimation();
     positionAnimation = polystarShape.getPosition().createAnimation();
     rotationAnimation = polystarShape.getRotation().createAnimation();
@@ -110,6 +112,11 @@
 
     path.reset();
 
+    if (hidden) {
+      isPathValid = true;
+      return path;
+    }
+
     switch (type) {
       case Star:
         createStarPath();
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/RectangleContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/RectangleContent.java
index 0b6ecbe..b546a09 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/RectangleContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/RectangleContent.java
@@ -23,6 +23,7 @@
   private final RectF rect = new RectF();
 
   private final String name;
+  private final boolean hidden;
   private final LottieDrawable lottieDrawable;
   private final BaseKeyframeAnimation<?, PointF> positionAnimation;
   private final BaseKeyframeAnimation<?, PointF> sizeAnimation;
@@ -33,6 +34,7 @@
 
   public RectangleContent(LottieDrawable lottieDrawable, BaseLayer layer, RectangleShape rectShape) {
     name = rectShape.getName();
+    hidden = rectShape.isHidden();
     this.lottieDrawable = lottieDrawable;
     positionAnimation = rectShape.getPosition().createAnimation();
     sizeAnimation = rectShape.getSize().createAnimation();
@@ -78,6 +80,11 @@
 
     path.reset();
 
+    if (hidden) {
+      isPathValid = true;
+      return path;
+    }
+
     PointF size = sizeAnimation.getValue();
     float halfWidth = size.x / 2f;
     float halfHeight = size.y / 2f;
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
index 506fb43..a5b1308 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
@@ -29,6 +29,7 @@
   private final LottieDrawable lottieDrawable;
   private final BaseLayer layer;
   private final String name;
+  private final boolean hidden;
   private final BaseKeyframeAnimation<Float, Float> copies;
   private final BaseKeyframeAnimation<Float, Float> offset;
   private final TransformKeyframeAnimation transform;
@@ -39,6 +40,7 @@
     this.lottieDrawable = lottieDrawable;
     this.layer = layer;
     name = repeater.getName();
+    this.hidden = repeater.isHidden();
     copies = repeater.getCopies().createAnimation();
     layer.addAnimation(copies);
     copies.addUpdateListener(this);
@@ -78,7 +80,7 @@
       contentsIter.remove();
     }
     Collections.reverse(contents);
-    contentGroup = new ContentGroup(lottieDrawable, layer, "Repeater", contents, null);
+    contentGroup = new ContentGroup(lottieDrawable, layer, "Repeater", hidden, contents, null);
   }
 
   @Override public String getName() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java
index 5d45292..dbee08b 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java
@@ -16,6 +16,7 @@
   private final Path path = new Path();
 
   private final String name;
+  private final boolean hidden;
   private final LottieDrawable lottieDrawable;
   private final BaseKeyframeAnimation<?, Path> shapeAnimation;
 
@@ -24,6 +25,7 @@
 
   public ShapeContent(LottieDrawable lottieDrawable, BaseLayer layer, ShapePath shape) {
     name = shape.getName();
+    hidden = shape.isHidden();
     this.lottieDrawable = lottieDrawable;
     shapeAnimation = shape.getShapePath().createAnimation();
     layer.addAnimation(shapeAnimation);
@@ -58,6 +60,11 @@
 
     path.reset();
 
+    if (hidden) {
+      isPathValid = true;
+      return path;
+    }
+
     path.set(shapeAnimation.getValue());
     path.setFillType(Path.FillType.EVEN_ODD);
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
index 3e3f449..fe3b90a 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
@@ -19,6 +19,7 @@
 
   private final BaseLayer layer;
   private final String name;
+  private final boolean hidden;
   private final BaseKeyframeAnimation<Integer, Integer> colorAnimation;
   @Nullable private BaseKeyframeAnimation<ColorFilter, ColorFilter> colorFilterAnimation;
 
@@ -28,12 +29,16 @@
         stroke.getWidth(), stroke.getLineDashPattern(), stroke.getDashOffset());
     this.layer = layer;
     name = stroke.getName();
+    hidden = stroke.isHidden();
     colorAnimation = stroke.getColor().createAnimation();
     colorAnimation.addUpdateListener(this);
     layer.addAnimation(colorAnimation);
   }
 
   @Override public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
+    if (hidden) {
+      return;
+    }
     paint.setColor(colorAnimation.getValue());
     if (colorFilterAnimation != null) {
       paint.setColorFilter(colorFilterAnimation.getValue());
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/TrimPathContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/TrimPathContent.java
index 30ad200..9dd77b2 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/TrimPathContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/TrimPathContent.java
@@ -10,6 +10,7 @@
 public class TrimPathContent implements Content, BaseKeyframeAnimation.AnimationListener {
 
   private final String name;
+  private final boolean hidden;
   private final List<BaseKeyframeAnimation.AnimationListener> listeners = new ArrayList<>();
   private final ShapeTrimPath.Type type;
   private final BaseKeyframeAnimation<?, Float> startAnimation;
@@ -18,6 +19,7 @@
 
   public TrimPathContent(BaseLayer layer, ShapeTrimPath trimPath) {
     name = trimPath.getName();
+    hidden = trimPath.isHidden();
     type = trimPath.getType();
     startAnimation = trimPath.getStart().createAnimation();
     endAnimation = trimPath.getEnd().createAnimation();
@@ -65,4 +67,8 @@
   public BaseKeyframeAnimation<?, Float> getOffset() {
     return offsetAnimation;
   }
+
+  public boolean isHidden() {
+    return hidden;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/CircleShape.java b/lottie/src/main/java/com/airbnb/lottie/model/content/CircleShape.java
index 49b5794..64adcba 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/CircleShape.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/CircleShape.java
@@ -14,13 +14,15 @@
   private final AnimatableValue<PointF, PointF> position;
   private final AnimatablePointValue size;
   private final boolean isReversed;
+  private final boolean hidden;
 
   public CircleShape(String name, AnimatableValue<PointF, PointF> position,
-      AnimatablePointValue size, boolean isReversed) {
+                     AnimatablePointValue size, boolean isReversed, boolean hidden) {
     this.name = name;
     this.position = position;
     this.size = size;
     this.isReversed = isReversed;
+    this.hidden = hidden;
   }
 
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
@@ -42,4 +44,8 @@
   public boolean isReversed() {
     return isReversed;
   }
+
+  public boolean isHidden() {
+    return hidden;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientFill.java b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientFill.java
index 090d8fe..cd25721 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientFill.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientFill.java
@@ -23,12 +23,13 @@
   private final String name;
   @Nullable private final AnimatableFloatValue highlightLength;
   @Nullable private final AnimatableFloatValue highlightAngle;
+  private final boolean hidden;
 
   public GradientFill(String name, GradientType gradientType, Path.FillType fillType,
-      AnimatableGradientColorValue gradientColor,
-      AnimatableIntegerValue opacity, AnimatablePointValue startPoint,
-      AnimatablePointValue endPoint, AnimatableFloatValue highlightLength,
-      AnimatableFloatValue highlightAngle) {
+                      AnimatableGradientColorValue gradientColor,
+                      AnimatableIntegerValue opacity, AnimatablePointValue startPoint,
+                      AnimatablePointValue endPoint, AnimatableFloatValue highlightLength,
+                      AnimatableFloatValue highlightAngle, boolean hidden) {
     this.gradientType = gradientType;
     this.fillType = fillType;
     this.gradientColor = gradientColor;
@@ -38,6 +39,7 @@
     this.name = name;
     this.highlightLength = highlightLength;
     this.highlightAngle = highlightAngle;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -76,6 +78,10 @@
     return highlightAngle;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new GradientFillContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientStroke.java b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientStroke.java
index 671aeba..d9b27a5 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/GradientStroke.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/GradientStroke.java
@@ -27,14 +27,15 @@
   private final float miterLimit;
   private final List<AnimatableFloatValue> lineDashPattern;
   @Nullable private final AnimatableFloatValue dashOffset;
+  private final boolean hidden;
 
   public GradientStroke(String name, GradientType gradientType,
-      AnimatableGradientColorValue gradientColor,
-      AnimatableIntegerValue opacity, AnimatablePointValue startPoint,
-      AnimatablePointValue endPoint, AnimatableFloatValue width, ShapeStroke.LineCapType capType,
-      ShapeStroke.LineJoinType joinType, float miterLimit,
-      List<AnimatableFloatValue> lineDashPattern,
-      @Nullable AnimatableFloatValue dashOffset) {
+                        AnimatableGradientColorValue gradientColor,
+                        AnimatableIntegerValue opacity, AnimatablePointValue startPoint,
+                        AnimatablePointValue endPoint, AnimatableFloatValue width, ShapeStroke.LineCapType capType,
+                        ShapeStroke.LineJoinType joinType, float miterLimit,
+                        List<AnimatableFloatValue> lineDashPattern,
+                        @Nullable AnimatableFloatValue dashOffset, boolean hidden) {
     this.name = name;
     this.gradientType = gradientType;
     this.gradientColor = gradientColor;
@@ -47,6 +48,7 @@
     this.miterLimit = miterLimit;
     this.lineDashPattern = lineDashPattern;
     this.dashOffset = dashOffset;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -97,6 +99,10 @@
     return miterLimit;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new GradientStrokeContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/MergePaths.java b/lottie/src/main/java/com/airbnb/lottie/model/content/MergePaths.java
index d9345ea..5420988 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/MergePaths.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/MergePaths.java
@@ -38,10 +38,12 @@
 
   private final String name;
   private final MergePathsMode mode;
+  private final boolean hidden;
 
-  public MergePaths(String name, MergePathsMode mode) {
+  public MergePaths(String name, MergePathsMode mode, boolean hidden) {
     this.name = name;
     this.mode = mode;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -52,6 +54,10 @@
     return mode;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override @Nullable public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     if (!drawable.enableMergePathsForKitKatAndAbove()) {
       L.warn("Animation contains merge paths but they are disabled.");
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/PolystarShape.java b/lottie/src/main/java/com/airbnb/lottie/model/content/PolystarShape.java
index 640c1d4..523ba19 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/PolystarShape.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/PolystarShape.java
@@ -39,12 +39,13 @@
   private final AnimatableFloatValue outerRadius;
   private final AnimatableFloatValue innerRoundedness;
   private final AnimatableFloatValue outerRoundedness;
+  private final boolean hidden;
 
   public PolystarShape(String name, Type type, AnimatableFloatValue points,
-      AnimatableValue<PointF, PointF> position,
-      AnimatableFloatValue rotation, AnimatableFloatValue innerRadius,
-      AnimatableFloatValue outerRadius, AnimatableFloatValue innerRoundedness,
-      AnimatableFloatValue outerRoundedness) {
+                       AnimatableValue<PointF, PointF> position,
+                       AnimatableFloatValue rotation, AnimatableFloatValue innerRadius,
+                       AnimatableFloatValue outerRadius, AnimatableFloatValue innerRoundedness,
+                       AnimatableFloatValue outerRoundedness, boolean hidden) {
     this.name = name;
     this.type = type;
     this.points = points;
@@ -54,6 +55,7 @@
     this.outerRadius = outerRadius;
     this.innerRoundedness = innerRoundedness;
     this.outerRoundedness = outerRoundedness;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -92,6 +94,10 @@
     return outerRoundedness;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new PolystarContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java b/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
index 83a9784..eec2b66 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/RectangleShape.java
@@ -15,13 +15,15 @@
   private final AnimatableValue<PointF, PointF> position;
   private final AnimatablePointValue size;
   private final AnimatableFloatValue cornerRadius;
+  private final boolean hidden;
 
   public RectangleShape(String name, AnimatableValue<PointF, PointF> position,
-      AnimatablePointValue size, AnimatableFloatValue cornerRadius) {
+                        AnimatablePointValue size, AnimatableFloatValue cornerRadius, boolean hidden) {
     this.name = name;
     this.position = position;
     this.size = size;
     this.cornerRadius = cornerRadius;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -40,6 +42,10 @@
     return position;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new RectangleContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/Repeater.java b/lottie/src/main/java/com/airbnb/lottie/model/content/Repeater.java
index 2aa1c76..f8938f8 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/Repeater.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/Repeater.java
@@ -14,13 +14,15 @@
   private final AnimatableFloatValue copies;
   private final AnimatableFloatValue offset;
   private final AnimatableTransform transform;
+  private final boolean hidden;
 
   public Repeater(String name, AnimatableFloatValue copies, AnimatableFloatValue offset,
-      AnimatableTransform transform) {
+                  AnimatableTransform transform, boolean hidden) {
     this.name = name;
     this.copies = copies;
     this.offset = offset;
     this.transform = transform;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -39,6 +41,10 @@
     return transform;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Nullable @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new RepeaterContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
index 028b110..26e75d2 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeFill.java
@@ -16,14 +16,16 @@
   private final String name;
   @Nullable private final AnimatableColorValue color;
   @Nullable private final AnimatableIntegerValue opacity;
+  private final boolean hidden;
 
   public ShapeFill(String name, boolean fillEnabled, Path.FillType fillType,
-      @Nullable AnimatableColorValue color, @Nullable AnimatableIntegerValue opacity) {
+                   @Nullable AnimatableColorValue color, @Nullable AnimatableIntegerValue opacity, boolean hidden) {
     this.name = name;
     this.fillEnabled = fillEnabled;
     this.fillType = fillType;
     this.color = color;
     this.opacity = opacity;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -42,6 +44,10 @@
     return fillType;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new FillContent(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeGroup.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeGroup.java
index dba70a9..ed332bc 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeGroup.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeGroup.java
@@ -11,10 +11,12 @@
 public class ShapeGroup implements ContentModel {
   private final String name;
   private final List<ContentModel> items;
+  private final boolean hidden;
 
-  public ShapeGroup(String name, List<ContentModel> items) {
+  public ShapeGroup(String name, List<ContentModel> items, boolean hidden) {
     this.name = name;
     this.items = items;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -25,6 +27,10 @@
     return items;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new ContentGroup(drawable, layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
index 9dd2977..af16199 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapePath.java
@@ -10,11 +10,13 @@
   private final String name;
   private final int index;
   private final AnimatableShapeValue shapePath;
+  private final boolean hidden;
 
-  public ShapePath(String name, int index, AnimatableShapeValue shapePath) {
+  public ShapePath(String name, int index, AnimatableShapeValue shapePath, boolean hidden) {
     this.name = name;
     this.index = index;
     this.shapePath = shapePath;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -29,6 +31,10 @@
     return new ShapeContent(drawable, layer, this);
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public String toString() {
     return "ShapePath{" + "name=" + name +
         ", index=" + index +
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeStroke.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeStroke.java
index 1fabcd5..273cd31 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeStroke.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeStroke.java
@@ -59,11 +59,12 @@
   private final LineCapType capType;
   private final LineJoinType joinType;
   private final float miterLimit;
+  private final boolean hidden;
 
   public ShapeStroke(String name, @Nullable AnimatableFloatValue offset,
-      List<AnimatableFloatValue> lineDashPattern, AnimatableColorValue color,
-      AnimatableIntegerValue opacity, AnimatableFloatValue width, LineCapType capType,
-      LineJoinType joinType, float miterLimit) {
+                     List<AnimatableFloatValue> lineDashPattern, AnimatableColorValue color,
+                     AnimatableIntegerValue opacity, AnimatableFloatValue width, LineCapType capType,
+                     LineJoinType joinType, float miterLimit, boolean hidden) {
     this.name = name;
     this.offset = offset;
     this.lineDashPattern = lineDashPattern;
@@ -73,6 +74,7 @@
     this.capType = capType;
     this.joinType = joinType;
     this.miterLimit = miterLimit;
+    this.hidden = hidden;
   }
 
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
@@ -114,4 +116,8 @@
   public float getMiterLimit() {
     return miterLimit;
   }
+
+  public boolean isHidden() {
+    return hidden;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeTrimPath.java b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeTrimPath.java
index 43edbfc..fb7fa9e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeTrimPath.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/content/ShapeTrimPath.java
@@ -29,14 +29,16 @@
   private final AnimatableFloatValue start;
   private final AnimatableFloatValue end;
   private final AnimatableFloatValue offset;
+  private final boolean hidden;
 
   public ShapeTrimPath(String name, Type type, AnimatableFloatValue start,
-      AnimatableFloatValue end, AnimatableFloatValue offset) {
+                       AnimatableFloatValue end, AnimatableFloatValue offset, boolean hidden) {
     this.name = name;
     this.type = type;
     this.start = start;
     this.end = end;
     this.offset = offset;
+    this.hidden = hidden;
   }
 
   public String getName() {
@@ -59,6 +61,10 @@
     return offset;
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   @Override public Content toContent(LottieDrawable drawable, BaseLayer layer) {
     return new TrimPathContent(layer, this);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index 89b2790..67b11dd 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -179,7 +179,7 @@
   @Override
   public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
     L.beginSection(drawTraceName);
-    if (!visible) {
+    if (!visible || layerModel.isHidden()) {
       L.endSection(drawTraceName);
       return;
     }
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
index a936208..653c80f 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
@@ -54,14 +54,15 @@
   @Nullable private final AnimatableFloatValue timeRemapping;
   private final List<Keyframe<Float>> inOutKeyframes;
   private final MatteType matteType;
+  private final boolean hidden;
 
   public Layer(List<ContentModel> shapes, LottieComposition composition, String layerName, long layerId,
-      LayerType layerType, long parentId, @Nullable String refId, List<Mask> masks,
-      AnimatableTransform transform, int solidWidth, int solidHeight, int solidColor,
-      float timeStretch, float startFrame, int preCompWidth, int preCompHeight,
-      @Nullable AnimatableTextFrame text, @Nullable AnimatableTextProperties textProperties,
-      List<Keyframe<Float>> inOutKeyframes, MatteType matteType,
-      @Nullable AnimatableFloatValue timeRemapping) {
+               LayerType layerType, long parentId, @Nullable String refId, List<Mask> masks,
+               AnimatableTransform transform, int solidWidth, int solidHeight, int solidColor,
+               float timeStretch, float startFrame, int preCompWidth, int preCompHeight,
+               @Nullable AnimatableTextFrame text, @Nullable AnimatableTextProperties textProperties,
+               List<Keyframe<Float>> inOutKeyframes, MatteType matteType,
+               @Nullable AnimatableFloatValue timeRemapping, boolean hidden) {
     this.shapes = shapes;
     this.composition = composition;
     this.layerName = layerName;
@@ -83,6 +84,7 @@
     this.inOutKeyframes = inOutKeyframes;
     this.matteType = matteType;
     this.timeRemapping = timeRemapping;
+    this.hidden = hidden;
   }
 
   LottieComposition getComposition() {
@@ -173,6 +175,10 @@
     return toString("");
   }
 
+  public boolean isHidden() {
+    return hidden;
+  }
+
   public String toString(String prefix) {
     StringBuilder sb = new StringBuilder();
     sb.append(prefix).append(getName()).append("\n");
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
index 6ffdb75..0f274f0 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
@@ -21,7 +21,7 @@
     super(lottieDrawable, layerModel);
 
     // Naming this __container allows it to be ignored in KeyPath matching.
-    ShapeGroup shapeGroup = new ShapeGroup("__container", layerModel.getShapes());
+    ShapeGroup shapeGroup = new ShapeGroup("__container", layerModel.getShapes(), false);
     contentGroup = new ContentGroup(lottieDrawable, this, shapeGroup);
     contentGroup.setContents(Collections.<Content>emptyList(), Collections.<Content>emptyList());
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/CircleShapeParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/CircleShapeParser.java
index e5d075c..4f31633 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/CircleShapeParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/CircleShapeParser.java
@@ -20,6 +20,7 @@
     AnimatableValue<PointF, PointF> position = null;
     AnimatablePointValue size = null;
     boolean reversed = d == 3;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -32,6 +33,9 @@
         case "s":
           size = AnimatableValueParser.parsePoint(reader, composition);
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         case "d":
           // "d" is 2 for normal and 3 for reversed.
           reversed = reader.nextInt() == 3;
@@ -41,6 +45,6 @@
       }
     }
 
-    return new CircleShape(name, position, size, reversed);
+    return new CircleShape(name, position, size, reversed, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/GradientFillParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/GradientFillParser.java
index 8bc069a..9dadadd 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/GradientFillParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/GradientFillParser.java
@@ -25,6 +25,7 @@
     AnimatablePointValue startPoint = null;
     AnimatablePointValue endPoint = null;
     Path.FillType fillType = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -63,12 +64,15 @@
         case "r":
           fillType = reader.nextInt() == 1 ? Path.FillType.WINDING : Path.FillType.EVEN_ODD;
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
     return new GradientFill(
-        name, gradientType, fillType, color, opacity, startPoint, endPoint, null, null);
+        name, gradientType, fillType, color, opacity, startPoint, endPoint, null, null, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/GradientStrokeParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/GradientStrokeParser.java
index cf4d097..5d26436 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/GradientStrokeParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/GradientStrokeParser.java
@@ -32,6 +32,7 @@
     ShapeStroke.LineJoinType joinType = null;
     AnimatableFloatValue offset = null;
     float miterLimit = 0f;
+    boolean hidden = false;
 
 
     List<AnimatableFloatValue> lineDashPattern = new ArrayList<>();
@@ -82,6 +83,9 @@
         case "ml":
           miterLimit = (float) reader.nextDouble();
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         case "d":
           reader.beginArray();
           while (reader.hasNext()) {
@@ -121,6 +125,6 @@
 
     return new GradientStroke(
         name, gradientType, color, opacity, startPoint, endPoint, width, capType, joinType,
-        miterLimit, lineDashPattern, offset);
+        miterLimit, lineDashPattern, offset, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
index 87ee517..f5be26e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
@@ -31,7 +31,7 @@
         Layer.LayerType.PreComp, -1, null, Collections.<Mask>emptyList(),
         new AnimatableTransform(), 0, 0, 0, 0, 0,
         bounds.width(), bounds.height(), null, null, Collections.<Keyframe<Float>>emptyList(),
-        Layer.MatteType.None, null);
+        Layer.MatteType.None, null, false);
   }
 
   public static Layer parse(JsonReader reader, LottieComposition composition) throws IOException {
@@ -52,6 +52,7 @@
     float inFrame = 0f;
     float outFrame = 0f;
     String cl = null;
+    boolean hidden = false;
 
     Layer.MatteType matteType = Layer.MatteType.None;
     AnimatableTransform transform = null;
@@ -186,6 +187,9 @@
         case "cl":
           cl = reader.nextString();
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
@@ -222,6 +226,6 @@
     return new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId,
         masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame,
         preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType,
-        timeRemapping);
+        timeRemapping, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/MergePathsParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/MergePathsParser.java
index 8900627..6d6569d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/MergePathsParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/MergePathsParser.java
@@ -13,6 +13,7 @@
   static MergePaths parse(JsonReader reader) throws IOException {
     String name = null;
     MergePaths.MergePathsMode mode = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -22,11 +23,14 @@
         case "mm":
           mode =  MergePaths.MergePathsMode.forId(reader.nextInt());
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
-    return new MergePaths(name, mode);
+    return new MergePaths(name, mode, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/PolystarShapeParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/PolystarShapeParser.java
index 6f5b62f..0dbf824 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/PolystarShapeParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/PolystarShapeParser.java
@@ -25,6 +25,7 @@
     AnimatableFloatValue outerRoundedness = null;
     AnimatableFloatValue innerRadius = null;
     AnimatableFloatValue innerRoundedness = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -55,12 +56,16 @@
         case "is":
           innerRoundedness = AnimatableValueParser.parseFloat(reader, composition, false);
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
     return new PolystarShape(
-        name, type, points, position, rotation, innerRadius, outerRadius, innerRoundedness, outerRoundedness);
+        name, type, points, position, rotation, innerRadius, outerRadius,
+        innerRoundedness, outerRoundedness, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/RectangleShapeParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/RectangleShapeParser.java
index 60f4eb2..af21210 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/RectangleShapeParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/RectangleShapeParser.java
@@ -21,6 +21,7 @@
     AnimatableValue<PointF, PointF> position = null;
     AnimatablePointValue size = null;
     AnimatableFloatValue roundedness = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -37,11 +38,14 @@
         case "r":
           roundedness = AnimatableValueParser.parseFloat(reader, composition);
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
-    return new RectangleShape(name, position, size, roundedness);
+    return new RectangleShape(name, position, size, roundedness, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/RepeaterParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/RepeaterParser.java
index 617fca4..0b877df 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/RepeaterParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/RepeaterParser.java
@@ -19,6 +19,7 @@
     AnimatableFloatValue copies = null;
     AnimatableFloatValue offset = null;
     AnimatableTransform transform = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -34,11 +35,14 @@
         case "tr":
           transform = AnimatableTransformParser.parse(reader, composition);
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
-    return new Repeater(name, copies, offset, transform);
+    return new Repeater(name, copies, offset, transform, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeFillParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeFillParser.java
index 67d1db8..0aaf8e0 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeFillParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeFillParser.java
@@ -21,6 +21,7 @@
     AnimatableIntegerValue opacity = null;
     String name = null;
     int fillTypeInt = 1;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -39,12 +40,15 @@
         case "r":
           fillTypeInt = reader.nextInt();
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
     Path.FillType fillType = fillTypeInt == 1 ? Path.FillType.WINDING : Path.FillType.EVEN_ODD;
-    return new ShapeFill(name, fillEnabled, fillType, color, opacity);
+    return new ShapeFill(name, fillEnabled, fillType, color, opacity, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeGroupParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeGroupParser.java
index 86256e3..eb3bed9 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeGroupParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeGroupParser.java
@@ -17,6 +17,7 @@
   static ShapeGroup parse(
       JsonReader reader, LottieComposition composition) throws IOException {
     String name = null;
+    boolean hidden = false;
     List<ContentModel> items = new ArrayList<>();
 
     while (reader.hasNext()) {
@@ -24,6 +25,9 @@
         case "nm":
           name = reader.nextString();
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         case "it":
           reader.beginArray();
           while (reader.hasNext()) {
@@ -39,6 +43,6 @@
       }
     }
 
-    return new ShapeGroup(name, items);
+    return new ShapeGroup(name, items, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ShapePathParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ShapePathParser.java
index c02b911..4320012 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ShapePathParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ShapePathParser.java
@@ -17,6 +17,7 @@
     String name = null;
     int ind = 0;
     AnimatableShapeValue shape = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -29,11 +30,14 @@
         case "ks":
           shape = AnimatableValueParser.parseShapeData(reader, composition);
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
-    return new ShapePath(name, ind, shape);
+    return new ShapePath(name, ind, shape, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeStrokeParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeStrokeParser.java
index 656bb4d..cf0bb50 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeStrokeParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeStrokeParser.java
@@ -26,6 +26,7 @@
     ShapeStroke.LineJoinType joinType = null;
     AnimatableFloatValue offset = null;
     float miterLimit = 0f;
+    boolean hidden = false;
 
     List<AnimatableFloatValue> lineDashPattern = new ArrayList<>();
 
@@ -52,6 +53,9 @@
         case "ml":
           miterLimit =  (float) reader.nextDouble();
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         case "d":
           reader.beginArray();
           while (reader.hasNext()) {
@@ -96,6 +100,6 @@
     }
 
     return new ShapeStroke(
-        name, offset, lineDashPattern, color, opacity, width, capType, joinType, miterLimit);
+        name, offset, lineDashPattern, color, opacity, width, capType, joinType, miterLimit, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeTrimPathParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeTrimPathParser.java
index fee09cb..20df2a3 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/ShapeTrimPathParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/ShapeTrimPathParser.java
@@ -19,6 +19,7 @@
     AnimatableFloatValue start = null;
     AnimatableFloatValue end = null;
     AnimatableFloatValue offset = null;
+    boolean hidden = false;
 
     while (reader.hasNext()) {
       switch (reader.nextName()) {
@@ -37,11 +38,14 @@
         case "m":
           type = ShapeTrimPath.Type.forId(reader.nextInt());
           break;
+        case "hd":
+          hidden = reader.nextBoolean();
+          break;
         default:
           reader.skipValue();
       }
     }
 
-    return new ShapeTrimPath(name, type, start, end, offset);
+    return new ShapeTrimPath(name, type, start, end, offset, hidden);
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/Utils.java b/lottie/src/main/java/com/airbnb/lottie/utils/Utils.java
index dde5ad6..fae84ce 100644
--- a/lottie/src/main/java/com/airbnb/lottie/utils/Utils.java
+++ b/lottie/src/main/java/com/airbnb/lottie/utils/Utils.java
@@ -65,7 +65,7 @@
   }
 
   public static void applyTrimPathIfNeeded(Path path, @Nullable TrimPathContent trimPath) {
-    if (trimPath == null) {
+    if (trimPath == null || trimPath.isHidden()) {
       return;
     }
     applyTrimPathIfNeeded(path, trimPath.getStart().getValue() / 100f,