blob: 3255fb9768ba185f1f882291b906fc49551137ce [file] [log] [blame]
package com.airbnb.lottie.model;
import android.graphics.Rect;
import android.util.LongSparseArray;
import com.airbnb.lottie.L;
import com.airbnb.lottie.layers.LottieLayer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class LottieComposition {
/**
* The largest bitmap drawing cache can be is 8,294,400 bytes. There are 4 bytes per pixel leaving ~2.3M pixels available.
* Reduce the number a little bit for safety.
*
* Hopefully this can be hardware accelerated someday.
*/
private static final int MAX_PIXELS = 1000;
public static LottieComposition fromJson(JSONObject json) {
LottieComposition composition = new LottieComposition();
int width = -1;
int height = -1;
try {
width = json.getInt("w");
height = json.getInt("h");
} catch (JSONException e) {
// ignore.
}
if (width != -1 && height != -1) {
int scaledWidth = (int) (width * L.SCALE);
int scaledHeight = (int) (height * L.SCALE);
if (scaledWidth * scaledHeight > MAX_PIXELS) {
float factor = (float) MAX_PIXELS / (float) Math.max(scaledWidth, scaledHeight);
scaledWidth *= factor;
scaledHeight *= factor;
L.SCALE *= factor;
}
composition.bounds = new Rect(0, 0, scaledWidth, scaledHeight);
}
try {
composition.startFrame = json.getLong("ip");
composition.endFrame = json.getLong("op");
composition.frameRate = json.getInt("fr");
} catch (JSONException e) {
//
}
if (composition.endFrame != 0 && composition.frameRate != 0) {
long frameDuration = composition.endFrame - composition.startFrame;
composition.duration = (long) (frameDuration / (float) composition.frameRate * 1000);
}
try {
JSONArray jsonLayers = json.getJSONArray("layers");
for (int i = 0; i < jsonLayers.length(); i++) {
LottieLayer layer = LottieLayer.fromJson(jsonLayers.getJSONObject(i), composition);
composition.layers.add(layer);
composition.layerMap.put(layer.getId(), layer);
if (!layer.getMasks().isEmpty()) {
composition.hasMasks = true;
}
if (layer.getMatteType() != null && layer.getMatteType() != LottieLayer.MatteType.None) {
composition.hasMattes = true;
}
}
} catch (JSONException e) {
throw new IllegalStateException("Unable to find layers.", e);
}
return composition;
}
private final LongSparseArray<LottieLayer> layerMap = new LongSparseArray<>();
private final List<LottieLayer> layers = new ArrayList<>();
private Rect bounds;
private long startFrame;
private long endFrame;
private int frameRate;
private long duration;
private boolean hasMasks;
private boolean hasMattes;
public LottieLayer layerModelForId(long id) {
return layerMap.get(id);
}
public Rect getBounds() {
return bounds;
}
public long getDuration() {
return duration;
}
public long getEndFrame() {
return endFrame;
}
public int getFrameRate() {
return frameRate;
}
public List<LottieLayer> getLayers() {
return layers;
}
public long getStartFrame() {
return startFrame;
}
public boolean hasMasks() {
return hasMasks;
}
public boolean hasMattes() {
return hasMattes;
}
}