content: package com.airbnb.lottie;
  
  import android.graphics.Path;
  import android.graphics.PointF;
  import android.support.annotation.Nullable;
  
  import java.util.List;
  
  class EllipseContent implements PathContent, BaseKeyframeAnimation.AnimationListener {
    private static final float ELLIPSE_CONTROL_POINT_PERCENTAGE = 0.55228f;
  
    private final Path path = new Path();
  
    private final LottieDrawable lottieDrawable;
    private final BaseKeyframeAnimation<?, PointF> sizeAnimation;
    private final BaseKeyframeAnimation<?, PointF> positionAnimation;
  
    @Nullable private TrimPathContent trimPath;
    private boolean isPathValid;
  
    EllipseContent(LottieDrawable lottieDrawable, BaseLayer layer, CircleShape circleShape) {
      this.lottieDrawable = lottieDrawable;
      sizeAnimation = circleShape.getSize().createAnimation();
      positionAnimation = circleShape.getPosition().createAnimation();
  
      layer.addAnimation(sizeAnimation);
      layer.addAnimation(positionAnimation);
  
      sizeAnimation.addUpdateListener(this);
      positionAnimation.addUpdateListener(this);
    }
  
    @Override public void onValueChanged() {
      invalidate();
    }
  
    private void invalidate() {
      isPathValid = false;
      lottieDrawable.invalidateSelf();
    }
  
    @Override public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
      for (int i = 0; i < contentsBefore.size(); i++) {
        Content content = contentsBefore.get(i);
        if (content instanceof TrimPathContent) {
          trimPath = (TrimPathContent) content;
          trimPath.addListener(this);
        }
      }
    }
  
    @Override public Path getPath() {
      if (isPathValid) {
        return path;
      }
  
      path.reset();
  
  
      PointF size = sizeAnimation.getValue();
      float halfWidth = size.x / 2f;
      float halfHeight = size.y / 2f;
      // TODO: handle bounds
  
      float cpW = halfWidth * ELLIPSE_CONTROL_POINT_PERCENTAGE;
      float cpH = halfHeight * ELLIPSE_CONTROL_POINT_PERCENTAGE;
  
      path.reset();
      path.moveTo(0, -halfHeight);
      path.cubicTo(0 + cpW, -halfHeight, halfWidth, 0 - cpH, halfWidth, 0);
      path.cubicTo(halfWidth, 0 + cpH, 0 + cpW, halfHeight, 0, halfHeight);
      path.cubicTo(0 - cpW, halfHeight, -halfWidth, 0 + cpH, -halfWidth, 0);
      path.cubicTo(-halfWidth, 0 - cpH, 0 - cpW, -halfHeight, 0, -halfHeight);
  
      PointF position = positionAnimation.getValue();
      path.offset(position.x, position.y);
  
      path.close();
  
      Utils.applyTrimPathIfNeeded(path, trimPath);
  
      isPathValid = true;
      return path;
    }
  }
  