/** * Copyright (c) 2016-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.keyframes.model; import java.util.List; import java.util.Map; import android.graphics.Bitmap; import android.graphics.Matrix; import android.util.SparseArray; import com.facebook.keyframes.util.AnimationGroupSort; import com.facebook.keyframes.util.ArgCheckUtil; import com.facebook.keyframes.util.ListHelper; /** * The top level model object for one entire animated image. Global information such as frame rate * it was exported as, frame count, and canvas size are included here for renderers. */ public class KFImage { /** * The frame rate that this animation was exported at. This is needed to play back the animation * at the correct speed. It does not limit the playback to discrete frames per second. */ public static final String FRAME_RATE_JSON_FIELD = "frame_rate"; private final int mFrameRate; /** * The total number of frames for this animation. */ public static final String FRAME_COUNT_JSON_FIELD = "animation_frame_count"; private final int mFrameCount; /** * A list of all the feature layers for this image. */ public static final String FEATURES_JSON_FIELD = "features"; private final List<KFFeature> mFeatures; /** * A list of all the animation layers for this image. */ public static final String ANIMATION_GROUPS_JSON_FIELD = "animation_groups"; private final List<KFAnimationGroup> mAnimationGroups; /** * The canvas size that this image was initially exported as. */ public static final String CANVAS_SIZE_JSON_FIELD = "canvas_size"; private final float[] mCanvasSize; /** * An optional identification key for this image. */ public static final String KEY_JSON_FIELD = "key"; private final int mKey; /** * An optional map of bitmaps for this image. */ public static final String BITMAPS_JSON_FIELD = "bitmaps"; private final Map<String, Bitmap> mBitmaps; public static class Builder { public int frameRate; public int frameCount; public List<KFFeature> features; public List<KFAnimationGroup> animationGroups; public float[] canvasSize; public int key; public Map<String, Bitmap> bitmaps; public KFImage build() { return new KFImage(frameRate, frameCount, features, animationGroups, canvasSize, key, bitmaps); } } private KFImage( int frameRate, int frameCount, List<KFFeature> features, List<KFAnimationGroup> animationGroups, float[] canvasSize, int key, Map<String, Bitmap> bitmaps) { mFrameRate = ArgCheckUtil.checkArg( frameRate, frameRate > 0, FRAME_RATE_JSON_FIELD); mFrameCount = ArgCheckUtil.checkArg( frameCount, frameCount > 0, FRAME_COUNT_JSON_FIELD); mFeatures = ArgCheckUtil.checkArg( ListHelper.immutableOrEmpty(features), features.size() > 0, FEATURES_JSON_FIELD); animationGroups = AnimationGroupSort.sort(animationGroups); mAnimationGroups = ArgCheckUtil.checkArg( ListHelper.immutableOrEmpty(animationGroups), ArgCheckUtil.checkAnimationGroupIdUniqueness(animationGroups), ANIMATION_GROUPS_JSON_FIELD); mCanvasSize = ArgCheckUtil.checkArg( canvasSize, canvasSize.length == 2 && canvasSize[0] > 0 && canvasSize[1] > 0, CANVAS_SIZE_JSON_FIELD); mKey = key; mBitmaps = bitmaps; } public int getFrameRate() { return mFrameRate; } public int getFrameCount() { return mFrameCount; } public List<KFFeature> getFeatures() { return mFeatures; } public List<KFAnimationGroup> getAnimationGroups() { return mAnimationGroups; } /** * Given a map of group id and corresponding matrices, apply the current matrix state calculated * from progress in the animation to the matrix in the map. * @param matrixMap A prefilled map of animation group id -> matrix * @param frameProgress The progress in animation, given as a frame value */ public void setAnimationMatrices(SparseArray<Matrix> matrixMap, float frameProgress) { Matrix matrix; for (int groupIndex = 0, groupsLen = mAnimationGroups.size(); groupIndex < groupsLen; groupIndex++) { KFAnimationGroup group = mAnimationGroups.get(groupIndex); matrix = matrixMap.get(group.getGroupId()); matrix.reset(); if (group.getAnchorPoint() != null) { group.getAnchorPoint().apply(frameProgress, matrix); } for (int animationIndex = 0, animationsLen = group.getAnimations().size(); animationIndex < animationsLen; animationIndex++) { group.getAnimations().get(animationIndex).getAnimation().apply(frameProgress, matrix); } if (group.getParentGroup() > 0) { matrix.postConcat(matrixMap.get(group.getParentGroup())); } } } public float[] getCanvasSize() { return mCanvasSize; } public int getKey() { return mKey; } public Map<String, Bitmap> getBitmaps() { return mBitmaps; } }