Driics

Lottie

Apr 29th, 2023
986
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 46.35 KB | None | 0 0
  1.  
  2.  
  3. package ru.driics.playm8.components.lottie;
  4.  
  5. import android.content.Context;
  6. import android.graphics.Bitmap;
  7. import android.graphics.Canvas;
  8. import android.graphics.ColorFilter;
  9. import android.graphics.Paint;
  10. import android.graphics.PixelFormat;
  11. import android.graphics.Rect;
  12. import android.graphics.RectF;
  13. import android.graphics.drawable.Animatable;
  14. import android.graphics.drawable.BitmapDrawable;
  15. import android.os.Handler;
  16. import android.os.Looper;
  17. import android.text.TextUtils;
  18. import android.view.Display;
  19. import android.view.HapticFeedbackConstants;
  20. import android.view.View;
  21. import android.view.WindowManager;
  22.  
  23. import com.google.gson.Gson;
  24.  
  25. import java.io.File;
  26. import java.io.FileInputStream;
  27. import java.io.FileReader;
  28. import java.io.InputStream;
  29. import java.lang.ref.WeakReference;
  30. import java.util.ArrayList;
  31. import java.util.HashMap;
  32. import java.util.concurrent.CountDownLatch;
  33.  
  34. import ru.driics.playm8.MyApplication;
  35. import ru.driics.playm8.utils.AndroidUtils;
  36. import ru.driics.playm8.utils.ViewUtils;
  37. import ru.driics.playm8.utils.cache.BitmapsCache;
  38. import ru.driics.playm8.utils.cache.DispatchQueue;
  39. import ru.driics.playm8.utils.cache.DispatchQueuePool;
  40. import ru.driics.playm8.utils.cache.DispatchQueuePoolBackground;
  41. import ru.driics.playm8.utils.cache.Utils;
  42.  
  43. public class RLottieDrawable extends BitmapDrawable implements Animatable, BitmapsCache.Cacheable {
  44.  
  45.     private static final Rect tmp = new Rect();
  46.     public boolean skipFrameUpdate;
  47.  
  48.     public static native long create(String src, String json, int w, int h, int[] params, boolean precache, int[] colorReplacement, boolean limitFps, int fitzModifier);
  49.  
  50.     protected static native long createWithJson(String json, String name, int[] params, int[] colorReplacement);
  51.  
  52.     public static native void destroy(long ptr);
  53.  
  54.     private static native void setLayerColor(long ptr, String layer, int color);
  55.  
  56.     private static native void replaceColors(long ptr, int[] colorReplacement);
  57.  
  58.     public static native int getFrame(long ptr, int frame, Bitmap bitmap, int w, int h, int stride, boolean clear);
  59.  
  60.     protected final int width;
  61.     protected final int height;
  62.     protected final int[] metaData = new int[3];
  63.     protected int timeBetweenFrames;
  64.     protected int customEndFrame = -1;
  65.     protected boolean playInDirectionOfCustomEndFrame;
  66.     private int[] newReplaceColors;
  67.     private int[] pendingReplaceColors;
  68.     private HashMap<String, Integer> newColorUpdates = new HashMap<>();
  69.     private volatile HashMap<String, Integer> pendingColorUpdates = new HashMap<>();
  70.     private HashMap<Integer, Integer> vibrationPattern;
  71.     private boolean resetVibrationAfterRestart = false;
  72.     private boolean allowVibration = true;
  73.     public static Gson gson;
  74.  
  75.     private WeakReference<Runnable> frameReadyCallback;
  76.     protected WeakReference<Runnable> onFinishCallback;
  77.     private int finishFrame;
  78.  
  79.     private View currentParentView;
  80.  
  81.     protected int isDice;
  82.     protected int diceSwitchFramesCount = -1;
  83.  
  84.     protected int autoRepeat = 1;
  85.     protected int autoRepeatCount = -1;
  86.     protected int autoRepeatPlayCount;
  87.     protected long autoRepeatTimeout;
  88.  
  89.     private long lastFrameTime;
  90.     protected volatile boolean nextFrameIsLast;
  91.  
  92.     protected Runnable cacheGenerateTask;
  93.     protected Runnable loadFrameTask;
  94.     protected volatile Bitmap renderingBitmap;
  95.     protected volatile Bitmap nextRenderingBitmap;
  96.     protected volatile Bitmap backgroundBitmap;
  97.     protected boolean waitingForNextTask;
  98.  
  99.     protected CountDownLatch frameWaitSync;
  100.  
  101.     protected boolean destroyWhenDone;
  102.     private boolean decodeSingleFrame;
  103.     private boolean singleFrameDecoded;
  104.     private boolean forceFrameRedraw;
  105.     private boolean applyingLayerColors;
  106.     protected int currentFrame;
  107.     private boolean shouldLimitFps;
  108.     private boolean createdForFirstFrame;
  109.  
  110.     private float scaleX = 1.0f;
  111.     private float scaleY = 1.0f;
  112.     private boolean applyTransformation;
  113.     private boolean needScale;
  114.     private final RectF dstRect = new RectF();
  115.     private RectF[] dstRectBackground = new RectF[2];
  116.     private Paint[] backgroundPaint = new Paint[2];
  117.     protected static final Handler uiHandler = new Handler(Looper.getMainLooper());
  118.     protected volatile boolean isRunning;
  119.     protected volatile boolean isRecycled;
  120.     protected volatile long nativePtr;
  121.     protected volatile long secondNativePtr;
  122.     protected boolean loadingInBackground;
  123.     protected boolean secondLoadingInBackground;
  124.     protected boolean destroyAfterLoading;
  125.     protected int secondFramesCount;
  126.     protected volatile boolean setLastFrame;
  127.     private boolean fallbackCache;
  128.  
  129.     private boolean invalidateOnProgressSet;
  130.     private boolean isInvalid;
  131.     private boolean doNotRemoveInvalidOnFrameReady;
  132.  
  133.     private static ThreadLocal<byte[]> readBufferLocal = new ThreadLocal<>();
  134.     private static ThreadLocal<byte[]> bufferLocal = new ThreadLocal<>();
  135.  
  136.     private static final DispatchQueuePool loadFrameRunnableQueue = new DispatchQueuePool(4);
  137.     public static DispatchQueue lottieCacheGenerateQueue;
  138.  
  139.     File file;
  140.     boolean precache;
  141.  
  142.     private Runnable onAnimationEndListener;
  143.     private Runnable onFrameReadyRunnable;
  144.  
  145.     private View masterParent;
  146.     NativePtrArgs args;
  147.  
  148.     Display display = ((WindowManager) MyApplication.applicationContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
  149.     float refreshRating = display.getRefreshRate();
  150.  
  151.     protected Runnable uiRunnableNoFrame = new Runnable() {
  152.         @Override
  153.         public void run() {
  154.             loadFrameTask = null;
  155.             decodeFrameFinishedInternal();
  156.             if (onFrameReadyRunnable != null) {
  157.                 onFrameReadyRunnable.run();
  158.             }
  159.         }
  160.     };
  161.  
  162.  
  163.     protected Runnable uiRunnable = new Runnable() {
  164.         @Override
  165.         public void run() {
  166.             singleFrameDecoded = true;
  167.             invalidateInternal();
  168.             decodeFrameFinishedInternal();
  169.             if (onFrameReadyRunnable != null) {
  170.                 onFrameReadyRunnable.run();
  171.             }
  172.         }
  173.     };
  174.  
  175.     boolean generatingCache;
  176.  
  177.     private Runnable uiRunnableGenerateCache = new Runnable() {
  178.         @Override
  179.         public void run() {
  180.             if (!isRecycled && !destroyWhenDone && canLoadFrames() && cacheGenerateTask == null) {
  181.                 generatingCache = true;
  182.                 if (lottieCacheGenerateQueue == null) {
  183.                     createCacheGenQueue();
  184.                 }
  185.                 BitmapsCache.incrementTaskCounter();
  186.                 lottieCacheGenerateQueue.postRunnable(cacheGenerateTask = () -> {
  187.                     try {
  188.                         BitmapsCache bitmapsCacheFinal = bitmapsCache;
  189.                         if (bitmapsCacheFinal != null) {
  190.                             bitmapsCacheFinal.createCache();
  191.                         }
  192.                     } catch (Throwable throwable) {
  193.  
  194.                     }
  195.                     uiHandler.post(uiRunnableCacheFinished);
  196.                 });
  197.             }
  198.         }
  199.     };
  200.  
  201.     private Runnable uiRunnableCacheFinished = new Runnable() {
  202.         @Override
  203.         public void run() {
  204.             if (cacheGenerateTask != null) {
  205.                 BitmapsCache.decrementTaskCounter();
  206.                 cacheGenerateTask = null;
  207.             }
  208.             generatingCache = false;
  209.             decodeFrameFinishedInternal();
  210.         }
  211.     };
  212.  
  213.     BitmapsCache bitmapsCache;
  214.     int generateCacheFramePointer;
  215.  
  216.     public static void createCacheGenQueue() {
  217.         lottieCacheGenerateQueue = new DispatchQueue("cache generator queue");
  218.     }
  219.  
  220.     protected void checkRunningTasks() {
  221.         if (cacheGenerateTask != null) {
  222.             lottieCacheGenerateQueue.cancelRunnable(cacheGenerateTask);
  223.             BitmapsCache.decrementTaskCounter();
  224.             cacheGenerateTask = null;
  225.         }
  226.         if (!hasParentView() && nextRenderingBitmap != null && loadFrameTask != null) {
  227.             loadFrameTask = null;
  228.             nextRenderingBitmap = null;
  229.         }
  230.     }
  231.  
  232.     protected void decodeFrameFinishedInternal() {
  233.         if (destroyWhenDone) {
  234.             checkRunningTasks();
  235.             if (loadFrameTask == null && cacheGenerateTask == null && nativePtr != 0) {
  236.                 recycleNativePtr(true);
  237.             }
  238.         }
  239.         if ((nativePtr == 0 || fallbackCache) && secondNativePtr == 0 && bitmapsCache == null) {
  240.             recycleResources();
  241.             return;
  242.         }
  243.         waitingForNextTask = true;
  244.         if (!hasParentView()) {
  245.             stop();
  246.         }
  247.         if (isRunning) {
  248.             scheduleNextGetFrame();
  249.         }
  250.     }
  251.  
  252.     private void recycleNativePtr(boolean uiThread) {
  253.         long nativePtrFinal = nativePtr;
  254.         long secondNativePtrFinal = secondNativePtr;
  255.  
  256.         nativePtr = 0;
  257.         secondNativePtr = 0;
  258.         if (nativePtrFinal != 0 || secondNativePtrFinal != 0) {
  259.             if (uiThread) {
  260.                 DispatchQueuePoolBackground.execute(() -> {
  261.                     if (nativePtrFinal != 0) {
  262.                         destroy(nativePtrFinal);
  263.                     }
  264.                     if (secondNativePtrFinal != 0) {
  265.                         destroy(secondNativePtrFinal);
  266.                     }
  267.                 });
  268.             } else {
  269.                 Utils.INSTANCE.getGlobalQueue().postRunnable(() -> {
  270.                     if (nativePtrFinal != 0) {
  271.                         destroy(nativePtrFinal);
  272.                     }
  273.                     if (secondNativePtrFinal != 0) {
  274.                         destroy(secondNativePtrFinal);
  275.                     }
  276.                 });
  277.             }
  278.         }
  279.     }
  280.  
  281.     protected void recycleResources() {
  282.         ArrayList<Bitmap> bitmapToRecycle = new ArrayList<>();
  283.         bitmapToRecycle.add(renderingBitmap);
  284.         bitmapToRecycle.add(backgroundBitmap);
  285.         bitmapToRecycle.add(nextRenderingBitmap);
  286.         nextRenderingBitmap = null;
  287.         renderingBitmap = null;
  288.         backgroundBitmap = null;
  289.         AndroidUtils.INSTANCE.recycleBitmaps(bitmapToRecycle);
  290.  
  291.         if (onAnimationEndListener != null) {
  292.             onAnimationEndListener = null;
  293.         }
  294.     }
  295.  
  296.     public void setOnFinishCallback(Runnable callback, int frame) {
  297.         if (callback != null) {
  298.             onFinishCallback = new WeakReference<>(callback);
  299.             finishFrame = frame;
  300.         } else if (onFinishCallback != null) {
  301.             onFinishCallback = null;
  302.         }
  303.     }
  304.  
  305.     private boolean genCacheSend;
  306.     protected Runnable loadFrameRunnable = new Runnable() {
  307.         private long lastUpdate = 0;
  308.  
  309.         @Override
  310.         public void run() {
  311.             if (isRecycled) {
  312.                 return;
  313.             }
  314.             if (!canLoadFrames() || isDice == 2 && secondNativePtr == 0) {
  315.                 if (frameWaitSync != null) {
  316.                     frameWaitSync.countDown();
  317.                 }
  318.                 uiHandler.post(uiRunnableNoFrame);
  319.                 return;
  320.             }
  321.             if (backgroundBitmap == null) {
  322.                 try {
  323.                     backgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  324.                 } catch (Throwable ignored) {
  325.  
  326.                 }
  327.             }
  328.             if (backgroundBitmap != null) {
  329.                 try {
  330.                     if (!pendingColorUpdates.isEmpty()) {
  331.                         for (HashMap.Entry<String, Integer> entry : pendingColorUpdates.entrySet()) {
  332.                             setLayerColor(nativePtr, entry.getKey(), entry.getValue());
  333.                         }
  334.                         pendingColorUpdates.clear();
  335.                     }
  336.                 } catch (Exception ignore) {
  337.  
  338.                 }
  339.                 if (pendingReplaceColors != null && nativePtr != 0) {
  340.                     replaceColors(nativePtr, pendingReplaceColors);
  341.                     pendingReplaceColors = null;
  342.                 }
  343.                 try {
  344.                     long ptrToUse;
  345.                     if (isDice == 1) {
  346.                         ptrToUse = nativePtr;
  347.                     } else if (isDice == 2) {
  348.                         ptrToUse = secondNativePtr;
  349.                         if (setLastFrame) {
  350.                             currentFrame = secondFramesCount - 1;
  351.                         }
  352.                     } else {
  353.                         ptrToUse = nativePtr;
  354.                     }
  355.                     int result = 0;
  356.                     int framesPerUpdates = shouldLimitFps ? 2 : 1;
  357.                     if (precache && bitmapsCache != null) {
  358.                         try {
  359.                             result = bitmapsCache.getFrame(currentFrame / framesPerUpdates, backgroundBitmap);
  360.                         } catch (Exception e) {
  361.                         }
  362.                     } else {
  363.                         result = getFrame(ptrToUse, currentFrame, backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), true);
  364.                     }
  365.                     if (bitmapsCache != null && bitmapsCache.needGenCache()) {
  366.                         if (!genCacheSend) {
  367.                             genCacheSend = true;
  368.                             uiHandler.post(uiRunnableGenerateCache);
  369.                         }
  370.                         result = -1;
  371.                     }
  372.                     if (result == -1) {
  373.                         uiHandler.post(uiRunnableNoFrame);
  374.                         if (frameWaitSync != null) {
  375.                             frameWaitSync.countDown();
  376.                         }
  377.                         return;
  378.                     }
  379.  
  380.                     nextRenderingBitmap = backgroundBitmap;
  381.  
  382.                     if (isDice == 1) {
  383.                         if (currentFrame + framesPerUpdates < (diceSwitchFramesCount == -1 ? metaData[0] : diceSwitchFramesCount)) {
  384.                             currentFrame += framesPerUpdates;
  385.                         } else {
  386.                             currentFrame = 0;
  387.                             nextFrameIsLast = false;
  388.                             if (secondNativePtr != 0) {
  389.                                 isDice = 2;
  390.                             }
  391.                             if (resetVibrationAfterRestart) {
  392.                                 vibrationPattern = null;
  393.                                 resetVibrationAfterRestart = false;
  394.                             }
  395.                         }
  396.                     } else if (isDice == 2) {
  397.                         if (currentFrame + framesPerUpdates < secondFramesCount) {
  398.                             currentFrame += framesPerUpdates;
  399.                         } else {
  400.                             nextFrameIsLast = true;
  401.                             autoRepeatPlayCount++;
  402.                         }
  403.                     } else {
  404.                         if (customEndFrame >= 0 && playInDirectionOfCustomEndFrame) {
  405.                             if (currentFrame > customEndFrame) {
  406.                                 if (currentFrame - framesPerUpdates >= customEndFrame) {
  407.                                     currentFrame -= framesPerUpdates;
  408.                                     nextFrameIsLast = false;
  409.                                 } else {
  410.                                     nextFrameIsLast = true;
  411.                                     checkDispatchOnAnimationEnd();
  412.                                 }
  413.                             } else {
  414.                                 if (currentFrame + framesPerUpdates < customEndFrame) {
  415.                                     currentFrame += framesPerUpdates;
  416.                                     nextFrameIsLast = false;
  417.                                 } else {
  418.                                     nextFrameIsLast = true;
  419.                                     checkDispatchOnAnimationEnd();
  420.                                 }
  421.                             }
  422.                         } else {
  423.                             if (currentFrame + framesPerUpdates < (customEndFrame >= 0 ? customEndFrame : metaData[0])) {
  424.                                 if (autoRepeat == 3) {
  425.                                     nextFrameIsLast = true;
  426.                                     autoRepeatPlayCount++;
  427.                                 } else {
  428.                                     currentFrame += framesPerUpdates;
  429.                                     nextFrameIsLast = false;
  430.                                 }
  431.                             } else if (autoRepeat == 1) {
  432.                                 currentFrame = 0;
  433.                                 nextFrameIsLast = false;
  434.                                 if (resetVibrationAfterRestart) {
  435.                                     vibrationPattern = null;
  436.                                     resetVibrationAfterRestart = false;
  437.                                 }
  438.                                 if (autoRepeatCount > 0) {
  439.                                     autoRepeatCount--;
  440.                                 }
  441.                             } else if (autoRepeat == 2) {
  442.                                 currentFrame = 0;
  443.                                 nextFrameIsLast = true;
  444.                                 autoRepeatPlayCount++;
  445.                                 if (resetVibrationAfterRestart) {
  446.                                     vibrationPattern = null;
  447.                                     resetVibrationAfterRestart = false;
  448.                                 }
  449.                             } else {
  450.                                 nextFrameIsLast = true;
  451.                                 checkDispatchOnAnimationEnd();
  452.                             }
  453.                         }
  454.                     }
  455.                 } catch (Exception e) {
  456.                 }
  457.             }
  458.             uiHandler.post(uiRunnable);
  459.             if (frameWaitSync != null) {
  460.                 frameWaitSync.countDown();
  461.             }
  462.         }
  463.     };
  464.  
  465.     public RLottieDrawable(File file, int w, int h, BitmapsCache.CacheOptions cacheOptions, boolean limitFps) {
  466.         this(file, w, h, cacheOptions, limitFps, null, 0);
  467.     }
  468.  
  469.     public RLottieDrawable(File file, int w, int h, BitmapsCache.CacheOptions cacheOptions, boolean limitFps, int[] colorReplacement, int fitzModifier) {
  470.         width = w;
  471.         height = h;
  472.         shouldLimitFps = limitFps;
  473.         this.precache = cacheOptions != null;
  474.         this.fallbackCache = cacheOptions != null && cacheOptions.fallback;
  475.         this.createdForFirstFrame = cacheOptions != null && cacheOptions.firstFrame;
  476.         getPaint().setFlags(Paint.FILTER_BITMAP_FLAG);
  477.  
  478.         this.file = file;
  479.         if (precache && lottieCacheGenerateQueue == null) {
  480.             createCacheGenQueue();
  481.         }
  482.         if (precache) {
  483.             args = new NativePtrArgs();
  484.             args.file = file.getAbsoluteFile();
  485.             args.json = null;
  486.             args.colorReplacement = colorReplacement;
  487.             args.fitzModifier = fitzModifier;
  488.             if (createdForFirstFrame) {
  489.                 return;
  490.             }
  491.             parseLottieMetadata(file, null, metaData);
  492.             if (shouldLimitFps && metaData[1] < 60) {
  493.                 shouldLimitFps = false;
  494.             }
  495.             bitmapsCache = new BitmapsCache(file, this, cacheOptions, w, h, !limitFps);
  496.         } else {
  497.             nativePtr = create(file.getAbsolutePath(), null, w, h, metaData, precache, colorReplacement, shouldLimitFps, fitzModifier);
  498.             if (nativePtr == 0) {
  499.                 file.delete();
  500.             }
  501.             if (shouldLimitFps && metaData[1] < 60) {
  502.                 shouldLimitFps = false;
  503.             }
  504.         }
  505.  
  506.         timeBetweenFrames = Math.max(shouldLimitFps ? 33 : 16, (int) (1000.0f / metaData[1]));
  507.     }
  508.  
  509.     public RLottieDrawable(File file, String json, int w, int h, BitmapsCache.CacheOptions options, boolean limitFps, int[] colorReplacement, int fitzModifier) {
  510.         width = w;
  511.         height = h;
  512.         shouldLimitFps = limitFps;
  513.         this.precache = options != null;
  514.         this.createdForFirstFrame = options != null && options.firstFrame;
  515.         getPaint().setFlags(Paint.FILTER_BITMAP_FLAG);
  516.         if (precache && lottieCacheGenerateQueue == null) {
  517.             createCacheGenQueue();
  518.         }
  519.         if (precache) {
  520.             args = new NativePtrArgs();
  521.             args.file = file.getAbsoluteFile();
  522.             args.json = json;
  523.             args.colorReplacement = colorReplacement;
  524.             args.fitzModifier = fitzModifier;
  525.             if (createdForFirstFrame) {
  526.                 return;
  527.             }
  528.             parseLottieMetadata(file, json, metaData);
  529.             if (shouldLimitFps && metaData[1] < 60) {
  530.                 shouldLimitFps = false;
  531.             }
  532.             bitmapsCache = new BitmapsCache(file, this, options, w, h, !limitFps);
  533.         } else {
  534.             nativePtr = create(file.getAbsolutePath(), json, w, h, metaData, precache, colorReplacement, shouldLimitFps, fitzModifier);
  535.             if (nativePtr == 0) {
  536.                 file.delete();
  537.             }
  538.             if (shouldLimitFps && metaData[1] < 60) {
  539.                 shouldLimitFps = false;
  540.             }
  541.         }
  542.  
  543.  
  544.         timeBetweenFrames = Math.max(shouldLimitFps ? 33 : 16, (int) (1000.0f / metaData[1]));
  545.     }
  546.  
  547.     private void parseLottieMetadata(File file, String json, int[] metaData) {
  548.         if (gson == null) {
  549.             gson = new Gson();
  550.         }
  551.         try {
  552.             LottieMetadata lottieMetadata;
  553.             if (file != null) {
  554.                 FileReader reader = new FileReader(file.getAbsolutePath());
  555.                 lottieMetadata = gson.fromJson(reader, LottieMetadata.class);
  556.                 try {
  557.                     reader.close();
  558.                 } catch (Exception e) {
  559.  
  560.                 }
  561.             } else {
  562.                 lottieMetadata = gson.fromJson(json, LottieMetadata.class);
  563.             }
  564.             metaData[0] = (int) (lottieMetadata.op - lottieMetadata.ip);
  565.             metaData[1] = (int) lottieMetadata.fr;
  566.         } catch (Exception e) {
  567.             // ignore app center, try handle by old method
  568.             long nativePtr = create(file.getAbsolutePath(), json, width, height, metaData, false, args.colorReplacement, shouldLimitFps, args.fitzModifier);
  569.             if (nativePtr != 0) {
  570.                 destroy(nativePtr);
  571.             }
  572.         }
  573.     }
  574.  
  575.     public RLottieDrawable(int rawRes, String name, int w, int h) {
  576.         this(rawRes, name, w, h, true, null);
  577.     }
  578.  
  579.  
  580.     private void checkDispatchOnAnimationEnd() {
  581.         if (onAnimationEndListener != null) {
  582.             onAnimationEndListener.run();
  583.             onAnimationEndListener = null;
  584.         }
  585.     }
  586.  
  587.     public void setOnAnimationEndListener(Runnable onAnimationEndListener) {
  588.         this.onAnimationEndListener = onAnimationEndListener;
  589.     }
  590.  
  591.     public RLottieDrawable(int rawRes, String name, int w, int h, boolean startDecode, int[] colorReplacement) {
  592.         width = w;
  593.         height = h;
  594.         autoRepeat = 0;
  595.         String jsonString = readRes(null, rawRes);
  596.         if (TextUtils.isEmpty(jsonString)) {
  597.             return;
  598.         }
  599.         getPaint().setFlags(Paint.FILTER_BITMAP_FLAG);
  600.         nativePtr = createWithJson(jsonString, name, metaData, colorReplacement);
  601.         timeBetweenFrames = Math.max(16, (int) (1000.0f / metaData[1]));
  602.         if (startDecode) {
  603.             setAllowDecodeSingleFrame(true);
  604.         }
  605.     }
  606.  
  607.     public static String readRes(File path, int rawRes) {
  608.         int totalRead = 0;
  609.         byte[] readBuffer = readBufferLocal.get();
  610.         if (readBuffer == null) {
  611.             readBuffer = new byte[64 * 1024];
  612.             readBufferLocal.set(readBuffer);
  613.         }
  614.         InputStream inputStream = null;
  615.         try {
  616.             if (path != null) {
  617.                 inputStream = new FileInputStream(path);
  618.             } else {
  619.                 inputStream = MyApplication.applicationContext.getResources().openRawResource(rawRes);
  620.             }
  621.             int readLen;
  622.             byte[] buffer = bufferLocal.get();
  623.             if (buffer == null) {
  624.                 buffer = new byte[4096];
  625.                 bufferLocal.set(buffer);
  626.             }
  627.             while ((readLen = inputStream.read(buffer, 0, buffer.length)) >= 0) {
  628.                 if (readBuffer.length < totalRead + readLen) {
  629.                     byte[] newBuffer = new byte[readBuffer.length * 2];
  630.                     System.arraycopy(readBuffer, 0, newBuffer, 0, totalRead);
  631.                     readBuffer = newBuffer;
  632.                     readBufferLocal.set(readBuffer);
  633.                 }
  634.                 if (readLen > 0) {
  635.                     System.arraycopy(buffer, 0, readBuffer, totalRead, readLen);
  636.                     totalRead += readLen;
  637.                 }
  638.             }
  639.         } catch (Throwable e) {
  640.             return null;
  641.         } finally {
  642.             try {
  643.                 if (inputStream != null) {
  644.                     inputStream.close();
  645.                 }
  646.             } catch (Throwable ignore) {
  647.  
  648.             }
  649.         }
  650.  
  651.         return new String(readBuffer, 0, totalRead);
  652.     }
  653.  
  654.     public int getCurrentFrame() {
  655.         return currentFrame;
  656.     }
  657.  
  658.     public int getCustomEndFrame() {
  659.         return customEndFrame;
  660.     }
  661.  
  662.     public long getDuration() {
  663.         return (long) (metaData[0] / (float) metaData[1] * 1000);
  664.     }
  665.  
  666.     public void setPlayInDirectionOfCustomEndFrame(boolean value) {
  667.         playInDirectionOfCustomEndFrame = value;
  668.     }
  669.  
  670.     public boolean setCustomEndFrame(int frame) {
  671.         if (customEndFrame == frame || frame > metaData[0]) {
  672.             return false;
  673.         }
  674.         customEndFrame = frame;
  675.         return true;
  676.     }
  677.  
  678.     public int getFramesCount() {
  679.         return metaData[0];
  680.     }
  681.  
  682.     /*public void addParentView(ImageReceiver parent) {
  683.         if (parent == null) {
  684.             return;
  685.         }
  686.         parentViews.add(parent);
  687.     }
  688.  
  689.     public void removeParentView(ImageReceiver parent) {
  690.         if (parent == null) {
  691.             return;
  692.         }
  693.         parentViews.remove(parent);
  694.         checkCacheCancel();
  695.     }*/
  696.  
  697.     public void checkCacheCancel() {
  698.         if (bitmapsCache == null || lottieCacheGenerateQueue == null || cacheGenerateTask == null) {
  699.             return;
  700.         }
  701.         boolean mustCancel = /*parentViews.isEmpty() && */ getCallback() == null;
  702.         mustCancel = mustCancel && (masterParent == null || !masterParent.isAttachedToWindow());
  703.         if (mustCancel) {
  704.             if (cacheGenerateTask != null) {
  705.                 lottieCacheGenerateQueue.cancelRunnable(cacheGenerateTask);
  706.                 BitmapsCache.decrementTaskCounter();
  707.                 cacheGenerateTask = null;
  708.             }
  709.             generatingCache = false;
  710.             genCacheSend = false;
  711.         }
  712.     }
  713.  
  714.     protected boolean hasParentView() {
  715.         return /*!parentViews.isEmpty() ||*/ masterParent != null || getCallback() != null;
  716.     }
  717.  
  718.     protected void invalidateInternal() {
  719.         if (isRecycled) {
  720.             return;
  721.         }
  722.         /*for (int i = 0, N = parentViews.size(); i < N; i++) {
  723.             parentViews.get(i).invalidate();
  724.         }*/
  725.         if (masterParent != null) {
  726.             masterParent.invalidate();
  727.         }
  728.         if (getCallback() != null) {
  729.             invalidateSelf();
  730.         }
  731.     }
  732.  
  733.     public void setAllowDecodeSingleFrame(boolean value) {
  734.         decodeSingleFrame = value;
  735.         if (decodeSingleFrame) {
  736.             scheduleNextGetFrame();
  737.         }
  738.     }
  739.  
  740.     public void recycle(boolean uiThread) {
  741.         isRunning = false;
  742.         isRecycled = true;
  743.         checkRunningTasks();
  744.         if (loadingInBackground || secondLoadingInBackground) {
  745.             destroyAfterLoading = true;
  746.         } else if (loadFrameTask == null && cacheGenerateTask == null && !generatingCache) {
  747.             recycleNativePtr(uiThread);
  748.             if (bitmapsCache != null) {
  749.                 bitmapsCache.recycle();
  750.                 bitmapsCache = null;
  751.             }
  752.             recycleResources();
  753.         } else {
  754.             destroyWhenDone = true;
  755.         }
  756.     }
  757.  
  758.     public void setAutoRepeat(int value) {
  759.         if (autoRepeat == 2 && value == 3 && currentFrame != 0) {
  760.             return;
  761.         }
  762.         autoRepeat = value;
  763.     }
  764.  
  765.     public void setAutoRepeatCount(int count) {
  766.         autoRepeatCount = count;
  767.     }
  768.  
  769.     public void setAutoRepeatTimeout(long timeout) {
  770.         autoRepeatTimeout = timeout;
  771.     }
  772.  
  773.     @Override
  774.     protected void finalize() throws Throwable {
  775.         try {
  776.             recycle(false);
  777.         } finally {
  778.             super.finalize();
  779.         }
  780.     }
  781.  
  782.     @Override
  783.     public int getOpacity() {
  784.         return PixelFormat.TRANSPARENT;
  785.     }
  786.  
  787.     @Override
  788.     public void start() {
  789.         if (isRunning || autoRepeat >= 2 && autoRepeatPlayCount != 0 || customEndFrame == currentFrame) {
  790.             return;
  791.         }
  792.         isRunning = true;
  793.         if (invalidateOnProgressSet) {
  794.             isInvalid = true;
  795.             if (loadFrameTask != null) {
  796.                 doNotRemoveInvalidOnFrameReady = true;
  797.             }
  798.         }
  799.         scheduleNextGetFrame();
  800.         invalidateInternal();
  801.     }
  802.  
  803.     public boolean restart() {
  804.         return restart(false);
  805.     }
  806.  
  807.     public boolean restart(boolean force) {
  808.         if (!force && (autoRepeat < 2 || autoRepeatPlayCount == 0) && autoRepeatCount < 0) {
  809.             return false;
  810.         }
  811.         autoRepeatPlayCount = 0;
  812.         autoRepeat = 2;
  813.         start();
  814.         return true;
  815.     }
  816.  
  817.     public void setVibrationPattern(HashMap<Integer, Integer> pattern) {
  818.         vibrationPattern = pattern;
  819.     }
  820.  
  821.     public boolean hasVibrationPattern() {
  822.         return vibrationPattern != null;
  823.     }
  824.  
  825.     public void beginApplyLayerColors() {
  826.         applyingLayerColors = true;
  827.     }
  828.  
  829.     public void commitApplyLayerColors() {
  830.         if (!applyingLayerColors) {
  831.             return;
  832.         }
  833.         applyingLayerColors = false;
  834.         if (!isRunning && decodeSingleFrame) {
  835.             if (currentFrame <= 2) {
  836.                 currentFrame = 0;
  837.             }
  838.             nextFrameIsLast = false;
  839.             singleFrameDecoded = false;
  840.             if (!scheduleNextGetFrame()) {
  841.                 forceFrameRedraw = true;
  842.             }
  843.         }
  844.         invalidateInternal();
  845.     }
  846.  
  847.     public void replaceColors(int[] colors) {
  848.         newReplaceColors = colors;
  849.         requestRedrawColors();
  850.     }
  851.  
  852.     public void setLayerColor(String layerName, int color) {
  853.         newColorUpdates.put(layerName, color);
  854.         requestRedrawColors();
  855.     }
  856.  
  857.     private void requestRedrawColors() {
  858.         if (!applyingLayerColors && !isRunning && decodeSingleFrame) {
  859.             if (currentFrame <= 2) {
  860.                 currentFrame = 0;
  861.             }
  862.             nextFrameIsLast = false;
  863.             singleFrameDecoded = false;
  864.             if (!scheduleNextGetFrame()) {
  865.                 forceFrameRedraw = true;
  866.             }
  867.         }
  868.         invalidateInternal();
  869.     }
  870.  
  871.     protected boolean scheduleNextGetFrame() {
  872.         if (loadFrameTask != null || nextRenderingBitmap != null || !canLoadFrames() || loadingInBackground || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded)) {
  873.             return false;
  874.         }
  875.         if (generatingCache) {
  876.             return false;
  877.         }
  878.         if (!newColorUpdates.isEmpty()) {
  879.             pendingColorUpdates.putAll(newColorUpdates);
  880.             newColorUpdates.clear();
  881.         }
  882.         if (newReplaceColors != null) {
  883.             pendingReplaceColors = newReplaceColors;
  884.             newReplaceColors = null;
  885.         }
  886.         loadFrameTask = loadFrameRunnable;
  887.         if (shouldLimitFps && Thread.currentThread() == MyApplication.applicationHandler.getLooper().getThread()) {
  888.             DispatchQueuePoolBackground.execute(loadFrameTask, frameWaitSync != null);
  889.         } else {
  890.             loadFrameRunnableQueue.execute(loadFrameTask);
  891.         }
  892.         return true;
  893.     }
  894.  
  895.     public boolean isHeavyDrawable() {
  896.         return isDice == 0;
  897.     }
  898.  
  899.     @Override
  900.     public void stop() {
  901.         isRunning = false;
  902.     }
  903.  
  904.     public void setCurrentFrame(int frame) {
  905.         setCurrentFrame(frame, true);
  906.     }
  907.  
  908.     public void setCurrentFrame(int frame, boolean async) {
  909.         setCurrentFrame(frame, async, false);
  910.     }
  911.  
  912.     public void setCurrentFrame(int frame, boolean async, boolean resetFrame) {
  913.         if (frame < 0 || frame > metaData[0] || (currentFrame == frame && !resetFrame)) {
  914.             return;
  915.         }
  916.         currentFrame = frame;
  917.         nextFrameIsLast = false;
  918.         singleFrameDecoded = false;
  919.         if (invalidateOnProgressSet) {
  920.             isInvalid = true;
  921.             if (loadFrameTask != null) {
  922.                 doNotRemoveInvalidOnFrameReady = true;
  923.             }
  924.         }
  925.         if ((!async || resetFrame) && waitingForNextTask && nextRenderingBitmap != null) {
  926.             backgroundBitmap = nextRenderingBitmap;
  927.             nextRenderingBitmap = null;
  928.             loadFrameTask = null;
  929.             waitingForNextTask = false;
  930.         }
  931.         if (!async) {
  932.             if (loadFrameTask == null) {
  933.                 frameWaitSync = new CountDownLatch(1);
  934.             }
  935.         }
  936.         if (resetFrame && !isRunning) {
  937.             isRunning = true;
  938.         }
  939.         if (scheduleNextGetFrame()) {
  940.             if (!async) {
  941.                 try {
  942.                     frameWaitSync.await();
  943.                 } catch (Exception e) {
  944.  
  945.                 }
  946.                 frameWaitSync = null;
  947.             }
  948.         } else {
  949.             forceFrameRedraw = true;
  950.         }
  951.         invalidateSelf();
  952.     }
  953.  
  954.     public boolean isCacheFallbacked() {
  955.         return fallbackCache;
  956.     }
  957.  
  958.     public void setProgressMs(long ms) {
  959.         int frameNum = (int) ((Math.max(0, ms) / timeBetweenFrames) % metaData[0]);
  960.         setCurrentFrame(frameNum, true, true);
  961.     }
  962.  
  963.     public void setProgress(float progress) {
  964.         setProgress(progress, true);
  965.     }
  966.  
  967.     public void setProgress(float progress, boolean async) {
  968.         if (progress < 0.0f) {
  969.             progress = 0.0f;
  970.         } else if (progress > 1.0f) {
  971.             progress = 1.0f;
  972.         }
  973.         setCurrentFrame((int) (metaData[0] * progress), async);
  974.     }
  975.  
  976.     public void setCurrentParentView(View view) {
  977.         currentParentView = view;
  978.     }
  979.  
  980.  
  981.     @Override
  982.     public boolean isRunning() {
  983.         return isRunning;
  984.     }
  985.  
  986.     @Override
  987.     public int getIntrinsicHeight() {
  988.         return height;
  989.     }
  990.  
  991.     @Override
  992.     public int getIntrinsicWidth() {
  993.         return width;
  994.     }
  995.  
  996.     @Override
  997.     protected void onBoundsChange(Rect bounds) {
  998.         super.onBoundsChange(bounds);
  999.         applyTransformation = true;
  1000.     }
  1001.  
  1002.     private void setCurrentFrame(long now, long timeDiff, long timeCheck, boolean force) {
  1003.         backgroundBitmap = renderingBitmap;
  1004.         renderingBitmap = nextRenderingBitmap;
  1005.         nextRenderingBitmap = null;
  1006.         if (isDice == 2) {
  1007.             if (onFinishCallback != null && currentFrame - 1 >= finishFrame) {
  1008.                 Runnable runnable = onFinishCallback.get();
  1009.                 if (runnable != null) {
  1010.                     runnable.run();
  1011.                 }
  1012.                 onFinishCallback = null;
  1013.             }
  1014.         }
  1015.         if (nextFrameIsLast || autoRepeatCount == 0 && autoRepeat == 1) {
  1016.             stop();
  1017.         }
  1018.         loadFrameTask = null;
  1019.         if (doNotRemoveInvalidOnFrameReady) {
  1020.             doNotRemoveInvalidOnFrameReady = false;
  1021.         } else if (isInvalid) {
  1022.             isInvalid = false;
  1023.         }
  1024.         singleFrameDecoded = true;
  1025.         waitingForNextTask = false;
  1026.         if (refreshRating <= 60) {
  1027.             lastFrameTime = now;
  1028.         } else {
  1029.             lastFrameTime = now - Math.min(16, timeDiff - timeCheck);
  1030.         }
  1031.         if (force && forceFrameRedraw) {
  1032.             singleFrameDecoded = false;
  1033.             forceFrameRedraw = false;
  1034.         }
  1035.         if (isDice == 0) {
  1036.             if (onFinishCallback != null && currentFrame >= finishFrame) {
  1037.                 Runnable runnable = onFinishCallback.get();
  1038.                 if (runnable != null) {
  1039.                     runnable.run();
  1040.                 }
  1041.             }
  1042.         }
  1043.         scheduleNextGetFrame();
  1044.     }
  1045.  
  1046.     @Override
  1047.     public void draw(Canvas canvas) {
  1048.         drawInternal(canvas, null, false, 0, 0);
  1049.     }
  1050.  
  1051.     public void drawInBackground(Canvas canvas, float x, float y, float w, float h, int alpha, ColorFilter colorFilter, int threadIndex) {
  1052.         if (dstRectBackground[threadIndex] == null) {
  1053.             dstRectBackground[threadIndex] = new RectF();
  1054.             backgroundPaint[threadIndex] = new Paint(Paint.ANTI_ALIAS_FLAG);
  1055.             backgroundPaint[threadIndex].setFilterBitmap(true);
  1056.         }
  1057.         backgroundPaint[threadIndex].setAlpha(alpha);
  1058.         backgroundPaint[threadIndex].setColorFilter(colorFilter);
  1059.         dstRectBackground[threadIndex].set(x, y, x + w, y + h);
  1060.         drawInternal(canvas, null, true, 0, threadIndex);
  1061.     }
  1062.  
  1063.     public void draw(Canvas canvas, Paint paint) {
  1064.         drawInternal(canvas, paint, false, 0, 0);
  1065.     }
  1066.  
  1067.     public void drawInternal(Canvas canvas, Paint overridePaint, boolean drawInBackground, long time, int threadIndex) {
  1068.         if (!canLoadFrames() || destroyWhenDone) {
  1069.             return;
  1070.         }
  1071.         if (!drawInBackground) {
  1072.             updateCurrentFrame(time, false);
  1073.         }
  1074.  
  1075.         RectF rect = drawInBackground ? dstRectBackground[threadIndex] : dstRect;
  1076.         Paint paint = overridePaint != null ? overridePaint : (drawInBackground ? backgroundPaint[threadIndex] : getPaint());
  1077.  
  1078.         if (paint.getAlpha() == 0) {
  1079.             return;
  1080.         }
  1081.  
  1082.         if (!isInvalid && renderingBitmap != null) {
  1083.             float scaleX, scaleY;
  1084.             boolean needScale;
  1085.             if (!drawInBackground) {
  1086.                 rect.set(getBounds());
  1087.                 if (applyTransformation) {
  1088.                     this.scaleX = rect.width() / width;
  1089.                     this.scaleY = rect.height() / height;
  1090.                     applyTransformation = false;
  1091.                     this.needScale = !(Math.abs(rect.width() - width) < ViewUtils.INSTANCE.getToPx(1) && Math.abs(rect.height() - height) < ViewUtils.INSTANCE.getToPx(1));
  1092.                 }
  1093.                 scaleX = this.scaleX;
  1094.                 scaleY = this.scaleY;
  1095.                 needScale = this.needScale;
  1096.             } else {
  1097.                 scaleX = rect.width() / width;
  1098.                 scaleY = rect.height() / height;
  1099.                 needScale = !(Math.abs(rect.width() - width) < ViewUtils.INSTANCE.getToPx(1) && Math.abs(rect.height() - height) < ViewUtils.INSTANCE.getToPx(1));
  1100.             }
  1101.             if (!needScale) {
  1102.                 canvas.drawBitmap(renderingBitmap, rect.left, rect.top, paint);
  1103.             } else {
  1104.                 canvas.save();
  1105.                 canvas.translate(rect.left, rect.top);
  1106.                 canvas.scale(scaleX, scaleY);
  1107.                 canvas.drawBitmap(renderingBitmap, 0, 0, paint);
  1108.                 canvas.restore();
  1109.             }
  1110.  
  1111.             if (isRunning && !drawInBackground) {
  1112.                 invalidateInternal();
  1113.             }
  1114.         }
  1115.     }
  1116.  
  1117.     public void updateCurrentFrame(long time, boolean updateInBackground) {
  1118.         long now = time == 0 ? System.currentTimeMillis() : time;
  1119.         long timeDiff = now - lastFrameTime;
  1120.         int timeCheck;
  1121.         if (updateInBackground && !shouldLimitFps) {
  1122.             timeCheck = timeBetweenFrames - 16;
  1123.         } else if (refreshRating <= 60 || (updateInBackground && refreshRating <= 80)) {
  1124.             timeCheck = timeBetweenFrames - 6;
  1125.         } else {
  1126.             timeCheck = timeBetweenFrames;
  1127.         }
  1128.         if (isRunning) {
  1129.             if (renderingBitmap == null && nextRenderingBitmap == null) {
  1130.                 scheduleNextGetFrame();
  1131.             } else if (nextRenderingBitmap != null && (renderingBitmap == null || (timeDiff >= timeCheck && !skipFrameUpdate))) {
  1132.                 if (vibrationPattern != null && currentParentView != null && allowVibration) {
  1133.                     Integer force = vibrationPattern.get(currentFrame - 1);
  1134.                     if (force != null) {
  1135.                         currentParentView.performHapticFeedback(force == 1 ? HapticFeedbackConstants.LONG_PRESS : HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
  1136.                     }
  1137.                 }
  1138.                 setCurrentFrame(now, timeDiff, timeCheck, false);
  1139.             }
  1140.         } else if ((forceFrameRedraw || decodeSingleFrame && timeDiff >= timeCheck) && nextRenderingBitmap != null) {
  1141.             setCurrentFrame(now, timeDiff, timeCheck, true);
  1142.         }
  1143.     }
  1144.  
  1145.     public void setAllowVibration(boolean allow) {
  1146.         allowVibration = allow;
  1147.     }
  1148.  
  1149.     public void resetVibrationAfterRestart(boolean value) {
  1150.         resetVibrationAfterRestart = value;
  1151.     }
  1152.  
  1153.     @Override
  1154.     public int getMinimumHeight() {
  1155.         return height;
  1156.     }
  1157.  
  1158.     @Override
  1159.     public int getMinimumWidth() {
  1160.         return width;
  1161.     }
  1162.  
  1163.     public Bitmap getRenderingBitmap() {
  1164.         return renderingBitmap;
  1165.     }
  1166.  
  1167.     public Bitmap getNextRenderingBitmap() {
  1168.         return nextRenderingBitmap;
  1169.     }
  1170.  
  1171.     public Bitmap getBackgroundBitmap() {
  1172.         return backgroundBitmap;
  1173.     }
  1174.  
  1175.     public Bitmap getAnimatedBitmap() {
  1176.         if (renderingBitmap != null) {
  1177.             return renderingBitmap;
  1178.         } else if (nextRenderingBitmap != null) {
  1179.             return nextRenderingBitmap;
  1180.         }
  1181.         return null;
  1182.     }
  1183.  
  1184.     public boolean hasBitmap() {
  1185.         return !isRecycled && (renderingBitmap != null || nextRenderingBitmap != null) && !isInvalid;
  1186.     }
  1187.  
  1188.     public void setInvalidateOnProgressSet(boolean value) {
  1189.         invalidateOnProgressSet = value;
  1190.     }
  1191.  
  1192.     public boolean isGeneratingCache() {
  1193.         return cacheGenerateTask != null;
  1194.     }
  1195.  
  1196.     public void setOnFrameReadyRunnable(Runnable onFrameReadyRunnable) {
  1197.         this.onFrameReadyRunnable = onFrameReadyRunnable;
  1198.     }
  1199.  
  1200.     public boolean isLastFrame() {
  1201.         return currentFrame == getFramesCount() - 1;
  1202.     }
  1203.  
  1204.     long generateCacheNativePtr;
  1205.  
  1206.     @Override
  1207.     public void prepareForGenerateCache() {
  1208.         generateCacheNativePtr = create(args.file.toString(), args.json, width, height, createdForFirstFrame ? metaData : new int[3], false, args.colorReplacement, false, args.fitzModifier);
  1209.         if (generateCacheNativePtr == 0 && file != null) {
  1210.             file.delete();
  1211.         }
  1212.     }
  1213.  
  1214.     public void setGeneratingFrame(int i) {
  1215.         generateCacheFramePointer = i;
  1216.     }
  1217.  
  1218.     @Override
  1219.     public int getNextFrame(Bitmap bitmap) {
  1220.         if (generateCacheNativePtr == 0) {
  1221.             return -1;
  1222.         }
  1223.         int framesPerUpdates = shouldLimitFps ? 2 : 1;
  1224.  
  1225.         int result = getFrame(generateCacheNativePtr, generateCacheFramePointer, bitmap, width, height, bitmap.getRowBytes(), true);
  1226.         if (result == -5) {
  1227.             try {
  1228.                 Thread.sleep(100);
  1229.             } catch (InterruptedException e) {
  1230.                 e.printStackTrace();
  1231.             }
  1232.             return getNextFrame(bitmap);
  1233.         }
  1234.         generateCacheFramePointer += framesPerUpdates;
  1235.         if (generateCacheFramePointer > metaData[0]) {
  1236.             return 0;
  1237.         }
  1238.         return 1;
  1239.     }
  1240.  
  1241.     private int rawBackgroundBitmapFrame = -1;
  1242.  
  1243.     public void drawFrame(Canvas canvas, int frame) {
  1244.         if (rawBackgroundBitmapFrame != frame || backgroundBitmap == null) {
  1245.             if (backgroundBitmap == null) {
  1246.                 backgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  1247.             }
  1248.             int result = getFrame(nativePtr, rawBackgroundBitmapFrame = frame, backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), true);
  1249.         }
  1250.         tmp.set(0, 0, width, height);
  1251.         canvas.drawBitmap(backgroundBitmap, tmp, getBounds(), getPaint());
  1252.     }
  1253.  
  1254.     @Override
  1255.     public void releaseForGenerateCache() {
  1256.         if (generateCacheNativePtr != 0) {
  1257.             destroy(generateCacheNativePtr);
  1258.             generateCacheNativePtr = 0;
  1259.         }
  1260.     }
  1261.  
  1262.     @Override
  1263.     public Bitmap getFirstFrame(Bitmap bitmap) {
  1264.         long nativePtr = create(args.file.toString(), args.json, width, height, new int[3], false, args.colorReplacement, false, args.fitzModifier);
  1265.         if (nativePtr == 0) {
  1266.             return bitmap;
  1267.         }
  1268.         getFrame(nativePtr, 0, bitmap, width, height, bitmap.getRowBytes(), true);
  1269.         destroy(nativePtr);
  1270.         return bitmap;
  1271.     }
  1272.  
  1273.     public void setMasterParent(View parent) {
  1274.         masterParent = parent;
  1275.     }
  1276.  
  1277.     public boolean canLoadFrames() {
  1278.         if (precache) {
  1279.             return bitmapsCache != null || fallbackCache;
  1280.         } else {
  1281.             return nativePtr != 0;
  1282.         }
  1283.     }
  1284.  
  1285.     private static class NativePtrArgs {
  1286.         public int[] colorReplacement;
  1287.         public int fitzModifier;
  1288.         File file;
  1289.         String json;
  1290.     }
  1291.  
  1292.     public void checkCache(Runnable onReady) {
  1293.         if (bitmapsCache == null) {
  1294.             AndroidUtils.INSTANCE.runOnUIThread(onReady);
  1295.             return;
  1296.         }
  1297.  
  1298.         generatingCache = true;
  1299.         if (lottieCacheGenerateQueue == null) {
  1300.             createCacheGenQueue();
  1301.         }
  1302.         if (cacheGenerateTask == null) {
  1303.             BitmapsCache.incrementTaskCounter();
  1304.             lottieCacheGenerateQueue.postRunnable(cacheGenerateTask = () -> {
  1305.                 try {
  1306.                     BitmapsCache bitmapsCacheFinal = bitmapsCache;
  1307.                     if (bitmapsCacheFinal != null) {
  1308.                         bitmapsCacheFinal.createCache();
  1309.                     }
  1310.                 } catch (Throwable ignored) {
  1311.                 }
  1312.                 AndroidUtils.INSTANCE.runOnUIThread(() -> {
  1313.                     onReady.run();
  1314.                     if (cacheGenerateTask != null) {
  1315.                         cacheGenerateTask = null;
  1316.                         BitmapsCache.decrementTaskCounter();
  1317.                     }
  1318.                 });
  1319.             });
  1320.         }
  1321.     }
  1322.  
  1323.     private static class LottieMetadata {
  1324.         float fr;
  1325.         float op;
  1326.         float ip;
  1327.     }
  1328. }
Advertisement
Add Comment
Please, Sign In to add comment