internal static RectangleShape Parse(JsonReader reader, LottieComposition composition)
        {
            string name = null;
            IAnimatableValue <Vector2?, Vector2?> position = null;
            AnimatablePointValue size        = null;
            AnimatableFloatValue roundedness = null;

            while (reader.HasNext())
            {
                switch (reader.NextName())
                {
                case "nm":
                    name = reader.NextString();
                    break;

                case "p":
                    position = AnimatablePathValueParser.ParseSplitPath(reader, composition);
                    break;

                case "s":
                    size = AnimatableValueParser.ParsePoint(reader, composition);
                    break;

                case "r":
                    roundedness = AnimatableValueParser.ParseFloat(reader, composition);
                    break;

                default:
                    reader.SkipValue();
                    break;
                }
            }

            return(new RectangleShape(name, position, size, roundedness));
        }
        internal static CircleShape Parse(JsonReader reader, LottieComposition composition, int d)
        {
            string name = null;
            IAnimatableValue <Vector2?, Vector2?> position = null;
            AnimatablePointValue size = null;
            bool reversed             = d == 3;
            bool hidden = false;

            while (reader.HasNext())
            {
                switch (reader.NextName())
                {
                case "nm":
                    name = reader.NextString();
                    break;

                case "p":
                    position = AnimatablePathValueParser.ParseSplitPath(reader, composition);
                    break;

                case "s":
                    size = AnimatableValueParser.ParsePoint(reader, composition);
                    break;

                case "d":
                    // "d" is 2 for normal and 3 for reversed.
                    reversed = reader.NextInt() == 3;
                    break;

                case "hd":
                    hidden = reader.NextBoolean();
                    break;

                default:
                    reader.SkipValue();
                    break;
                }
            }

            return(new CircleShape(name, position, size, reversed, hidden));
        }
        internal static PolystarShape Parse(JsonReader reader, LottieComposition composition)
        {
            string name = null;

            PolystarShape.Type   type   = PolystarShape.Type.Polygon;
            AnimatableFloatValue points = null;
            IAnimatableValue <Vector2?, Vector2?> position = null;
            AnimatableFloatValue rotation         = null;
            AnimatableFloatValue outerRadius      = null;
            AnimatableFloatValue outerRoundedness = null;
            AnimatableFloatValue innerRadius      = null;
            AnimatableFloatValue innerRoundedness = null;

            while (reader.HasNext())
            {
                switch (reader.NextName())
                {
                case "nm":
                    name = reader.NextString();
                    break;

                case "sy":
                    type = (PolystarShape.Type)reader.NextInt();
                    break;

                case "pt":
                    points = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "p":
                    position = AnimatablePathValueParser.ParseSplitPath(reader, composition);
                    break;

                case "r":
                    rotation = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "or":
                    outerRadius = AnimatableValueParser.ParseFloat(reader, composition);
                    break;

                case "os":
                    outerRoundedness = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "ir":
                    innerRadius = AnimatableValueParser.ParseFloat(reader, composition);
                    break;

                case "is":
                    innerRoundedness = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                default:
                    reader.SkipValue();
                    break;
                }
            }

            return(new PolystarShape(name, type, points, position, rotation, innerRadius, outerRadius, innerRoundedness, outerRoundedness));
        }
        public static AnimatableTransform Parse(JsonReader reader, LottieComposition composition)
        {
            AnimatablePathValue anchorPoint = null;
            IAnimatableValue <Vector2?, Vector2?> position = null;
            AnimatableScaleValue   scale        = null;
            AnimatableFloatValue   rotation     = null;
            AnimatableIntegerValue opacity      = null;
            AnimatableFloatValue   startOpacity = null;
            AnimatableFloatValue   endOpacity   = null;

            bool isObject = reader.Peek() == JsonToken.StartObject;

            if (isObject)
            {
                reader.BeginObject();
            }
            while (reader.HasNext())
            {
                switch (reader.NextName())
                {
                case "a":
                    reader.BeginObject();
                    while (reader.HasNext())
                    {
                        if (reader.NextName().Equals("k"))
                        {
                            anchorPoint = AnimatablePathValueParser.Parse(reader, composition);
                        }
                        else
                        {
                            reader.SkipValue();
                        }
                    }
                    reader.EndObject();
                    break;

                case "p":
                    position = AnimatablePathValueParser.ParseSplitPath(reader, composition);
                    break;

                case "s":
                    scale = AnimatableValueParser.ParseScale(reader, composition);
                    break;

                case "rz":
                    composition.AddWarning("Lottie doesn't support 3D layers.");
                    rotation = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "r":
                    rotation = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "o":
                    opacity = AnimatableValueParser.ParseInteger(reader, composition);
                    break;

                case "so":
                    startOpacity = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                case "eo":
                    endOpacity = AnimatableValueParser.ParseFloat(reader, composition, false);
                    break;

                default:
                    reader.SkipValue();
                    break;
                }
            }
            if (isObject)
            {
                reader.EndObject();
            }

            if (anchorPoint == null)
            {
                // Cameras don't have an anchor point property. Although we don't support them, at least
                // we won't crash.
                Debug.WriteLine("Layer has no transform property. You may be using an unsupported layer type such as a camera.", LottieLog.Tag);
                anchorPoint = new AnimatablePathValue();
            }

            if (scale == null)
            {
                // Somehow some community animations don't have scale in the transform.
                scale = new AnimatableScaleValue(new ScaleXy(1f, 1f));
            }

            if (opacity == null)
            {
                // Repeaters have start/end opacity instead of opacity
                opacity = new AnimatableIntegerValue();
            }

            return(new AnimatableTransform(
                       anchorPoint, position, scale, rotation, opacity, startOpacity, endOpacity));
        }