Don't set LottieDrawable bounds from within itself
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index 18ff5c8..450dfa4 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -214,9 +214,6 @@
       setRenderMode(RenderMode.values()[renderModeOrdinal]);
     }
 
-    if (getScaleType() != null) {
-      lottieDrawable.setScaleType(getScaleType());
-    }
     ta.recycle();
 
     lottieDrawable.setSystemAnimationsAreEnabled(Utils.getAnimationScale(getContext()) != 0f);
@@ -967,13 +964,6 @@
     return lottieDrawable.getScale();
   }
 
-  @Override public void setScaleType(ScaleType scaleType) {
-    super.setScaleType(scaleType);
-    if (lottieDrawable != null) {
-      lottieDrawable.setScaleType(scaleType);
-    }
-  }
-
   @MainThread
   public void cancelAnimation() {
     wasAnimatingWhenDetached = false;
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index a274ab3..f2d7599 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -33,10 +33,8 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 
 import androidx.annotation.FloatRange;
 import androidx.annotation.IntDef;
@@ -51,10 +49,8 @@
  *
  * @see <a href="http://airbnb.io/lottie">Full Documentation</a>
  */
-@SuppressWarnings({"WeakerAccess", "unused"})
+@SuppressWarnings({"WeakerAccess"})
 public class LottieDrawable extends Drawable implements Drawable.Callback, Animatable {
-  private static final String TAG = LottieDrawable.class.getSimpleName();
-
   private interface LazyCompositionTask {
     void run(LottieComposition composition);
   }
@@ -66,7 +62,6 @@
   private boolean systemAnimationsEnabled = true;
   private boolean safeMode = false;
 
-  private final Set<ColorFilterData> colorFilterData = new HashSet<>();
   private final ArrayList<LazyCompositionTask> lazyCompositionTasks = new ArrayList<>();
   private final ValueAnimator.AnimatorUpdateListener  progressUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
     @Override
@@ -77,8 +72,6 @@
     }
   };
   @Nullable
-  private ImageView.ScaleType scaleType;
-  @Nullable
   private ImageAssetManager imageAssetManager;
   @Nullable
   private String imageAssetsFolder;
@@ -183,10 +176,6 @@
    * `setImageAssetsFolder("airbnb_loader/");`.
    * <p>
    * <p>
-   * If you use LottieDrawable directly, you MUST call {@link #recycleBitmaps()} when you
-   * are done. Calling {@link #recycleBitmaps()} doesn't have to be final and {@link LottieDrawable}
-   * will recreate the bitmaps if needed but they will leak if you don't recycle them.
-   * <p>
    * Be wary if you are using many images, however. Lottie is designed to work with vector shapes
    * from After Effects. If your images look like they could be represented with vector shapes,
    * see if it is possible to convert them to shape layers and re-export your animation. Check
@@ -219,7 +208,6 @@
     animator.setComposition(composition);
     setProgress(animator.getAnimatedFraction());
     setScale(scale);
-    updateBounds();
 
     // We copy the tasks to a new ArrayList so that if this method is called from multiple threads,
     // then there won't be two iterators iterating and removing at the same time.
@@ -395,13 +383,25 @@
   }
 
   private void drawInternal(@NonNull Canvas canvas) {
-    if (ImageView.ScaleType.FIT_XY == scaleType) {
+    if (!boundsMatchesCompositionAspectRatio()) {
       drawWithNewAspectRatio(canvas);
     } else {
       drawWithOriginalAspectRatio(canvas);
     }
   }
 
+  private boolean boundsMatchesCompositionAspectRatio() {
+    LottieComposition composition = this.composition;
+    if (composition == null) {
+      return true;
+    }
+    return aspectRatio(getBounds()) == aspectRatio(composition.getBounds());
+  }
+
+  private float aspectRatio(Rect rect) {
+    return rect.width() / (float) rect.height();
+  }
+
 // <editor-fold desc="animator">
 
   @MainThread
@@ -651,8 +651,8 @@
     }
     int startFrame = (int) startMarker.startFrame;
 
-    Marker endMarker = composition.getMarker(endMarkerName);
-    if (endMarkerName == null) {
+    final Marker endMarker = composition.getMarker(endMarkerName);
+    if (endMarker == null) {
       throw new IllegalArgumentException("Cannot find marker with name " + endMarkerName + ".");
     }
     int endFrame = (int) (endMarker.startFrame + (playEndMarkerStartFrame ? 1f : 0f));
@@ -855,6 +855,7 @@
   public boolean isAnimating() {
     // On some versions of Android, this is called from the LottieAnimationView constructor, before animator was created.
     // https://github.com/airbnb/lottie-android/issues/1430
+    //noinspection ConstantConditions
     if (animator == null) {
       return false;
     }
@@ -881,7 +882,6 @@
    */
   public void setScale(float scale) {
     this.scale = scale;
-    updateBounds();
   }
 
   /**
@@ -895,8 +895,7 @@
    * the documentation at http://airbnb.io/lottie for more information about importing shapes from
    * Sketch or Illustrator to avoid this.
    */
-  public void setImageAssetDelegate(
-      @SuppressWarnings("NullableProblems") ImageAssetDelegate assetDelegate) {
+  public void setImageAssetDelegate(ImageAssetDelegate assetDelegate) {
     this.imageAssetDelegate = assetDelegate;
     if (imageAssetManager != null) {
       imageAssetManager.setDelegate(assetDelegate);
@@ -906,8 +905,7 @@
   /**
    * Use this to manually set fonts.
    */
-  public void setFontAssetDelegate(
-      @SuppressWarnings("NullableProblems") FontAssetDelegate assetDelegate) {
+  public void setFontAssetDelegate(FontAssetDelegate assetDelegate) {
     this.fontAssetDelegate = assetDelegate;
     if (fontAssetManager != null) {
       fontAssetManager.setDelegate(assetDelegate);
@@ -935,15 +933,6 @@
     return composition;
   }
 
-  private void updateBounds() {
-    if (composition == null) {
-      return;
-    }
-    float scale = getScale();
-    setBounds(0, 0, (int) (composition.getBounds().width() * scale),
-        (int) (composition.getBounds().height() * scale));
-  }
-
   public void cancelAnimation() {
     lazyCompositionTasks.clear();
     animator.cancel();
@@ -989,7 +978,7 @@
 
   /**
    * Add an property callback for the specified {@link KeyPath}. This {@link KeyPath} can resolve
-   * to multiple contents. In that case, the callbacks's value will apply to all of them.
+   * to multiple contents. In that case, the callback's value will apply to all of them.
    * <p>
    * Internally, this will check if the {@link KeyPath} has already been resolved with
    * {@link #resolveKeyPath(KeyPath)} and will resolve it if it hasn't.
@@ -1160,10 +1149,6 @@
     callback.unscheduleDrawable(this, what);
   }
 
-  void setScaleType(ImageView.ScaleType scaleType) {
-    this.scaleType = scaleType;
-  }
-
   /**
    * If the composition is larger than the canvas, we have to use a different method to scale it up.
    * See the comments in {@link #draw(Canvas)} for more info.
@@ -1261,49 +1246,4 @@
       canvas.restoreToCount(saveCount);
     }
   }
-
-  private static class ColorFilterData {
-
-    final String layerName;
-    @Nullable
-    final String contentName;
-    @Nullable
-    final ColorFilter colorFilter;
-
-    ColorFilterData(@Nullable String layerName, @Nullable String contentName,
-                    @Nullable ColorFilter colorFilter) {
-      this.layerName = layerName;
-      this.contentName = contentName;
-      this.colorFilter = colorFilter;
-    }
-
-    @Override
-    public int hashCode() {
-      int hashCode = 17;
-      if (layerName != null) {
-        hashCode = hashCode * 31 * layerName.hashCode();
-      }
-
-      if (contentName != null) {
-        hashCode = hashCode * 31 * contentName.hashCode();
-      }
-      return hashCode;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (this == obj) {
-        return true;
-      }
-
-      if (!(obj instanceof ColorFilterData)) {
-        return false;
-      }
-
-      final ColorFilterData other = (ColorFilterData) obj;
-
-      return hashCode() == other.hashCode() && colorFilter == other.colorFilter;
-
-    }
-  }
 }
diff --git a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
index 4782009..21bc724 100644
--- a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
+++ b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
@@ -101,6 +101,7 @@
     @Test
     fun testAll() = runBlocking {
         withTimeout(TimeUnit.MINUTES.toMillis(45)) {
+            testCustomBounds()
             testColorStateListColorFilter()
             testFailure()
             snapshotFrameBoundaries()
@@ -1002,6 +1003,25 @@
         }
     }
 
+    private suspend fun testCustomBounds() {
+        val composition = LottieCompositionFactory.fromRawResSync(application, R.raw.heart).value!!
+        val bitmap = bitmapPool.acquire(50, 100)
+        val canvas = Canvas(bitmap)
+        val drawable = LottieDrawable()
+        drawable.composition = composition
+        drawable.repeatCount = Integer.MAX_VALUE
+        drawable.setBounds(0, 0, 25, 100)
+        withContext(Dispatchers.Main) {
+            drawable.draw(canvas)
+        }
+        LottieCompositionCache.getInstance().clear()
+        snapshotter.record(bitmap, "CustomBounds", "Heart-25x100")
+        snapshotActivityRule.scenario.onActivity { activity ->
+            activity.recordSnapshot("CustomBounds", "Heart-25x100")
+        }
+        bitmapPool.release(bitmap)
+    }
+
     private suspend fun testColorStateListColorFilter() {
         log("Testing color filter")
         val context = ContextThemeWrapper(application, R.style.AppTheme)