/*
* Copyright (c) 2015-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.imagepipeline.animated.factory;
import java.util.concurrent.ScheduledExecutorService;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.graphics.drawable.Drawable;
import com.facebook.common.time.MonotonicClock;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.animated.base.AnimatedDrawable;
import com.facebook.imagepipeline.animated.base.AnimatedDrawableBackend;
import com.facebook.imagepipeline.animated.base.AnimatedDrawableCachingBackend;
import com.facebook.imagepipeline.animated.base.AnimatedDrawableDiagnostics;
import com.facebook.imagepipeline.animated.base.AnimatedDrawableOptions;
import com.facebook.imagepipeline.animated.base.AnimatedImage;
import com.facebook.imagepipeline.animated.base.AnimatedImageResult;
import com.facebook.imagepipeline.animated.impl.AnimatedDrawableBackendProvider;
import com.facebook.imagepipeline.animated.impl.AnimatedDrawableCachingBackendImplProvider;
import com.facebook.imagepipeline.animated.impl.AnimatedDrawableDiagnosticsImpl;
import com.facebook.imagepipeline.animated.impl.AnimatedDrawableDiagnosticsNoop;
import com.facebook.imagepipeline.animated.util.AnimatedDrawableUtil;
import com.facebook.imagepipeline.image.CloseableAnimatedImage;
/**
* Factory for instances of {@link AnimatedDrawable}.
*/
public class AnimatedDrawableFactoryImpl implements AnimatedDrawableFactory {
private final AnimatedDrawableBackendProvider mAnimatedDrawableBackendProvider;
private final AnimatedDrawableCachingBackendImplProvider mAnimatedDrawableCachingBackendProvider;
private final AnimatedDrawableUtil mAnimatedDrawableUtil;
private final ScheduledExecutorService mScheduledExecutorServiceForUiThread;
private final MonotonicClock mMonotonicClock;
private final Resources mResources;
public AnimatedDrawableFactoryImpl(
AnimatedDrawableBackendProvider animatedDrawableBackendProvider,
AnimatedDrawableCachingBackendImplProvider animatedDrawableCachingBackendProvider,
AnimatedDrawableUtil animatedDrawableUtil,
ScheduledExecutorService scheduledExecutorService,
Resources resources) {
mAnimatedDrawableBackendProvider = animatedDrawableBackendProvider;
mAnimatedDrawableCachingBackendProvider = animatedDrawableCachingBackendProvider;
mAnimatedDrawableUtil = animatedDrawableUtil;
mScheduledExecutorServiceForUiThread = scheduledExecutorService;
mMonotonicClock = new MonotonicClock() {
@Override
public long now() {
// Must be SystemClock.uptimeMillis to be compatible with what Android's View uses.
return SystemClock.uptimeMillis();
}
};
mResources = resources;
}
/**
* Creates an {@link AnimatedDrawable} based on an {@link CloseableImage} which should be a
* CloseableAnimatedImage.
*
* @param closeableImage The CloseableAnimatedImage to use for the AnimatedDrawable
* @return a newly constructed {@link AnimatedDrawable}
*/
@Override
public Drawable create(CloseableImage closeableImage) {
if (closeableImage instanceof CloseableAnimatedImage) {
final AnimatedImageResult result = ((CloseableAnimatedImage) closeableImage).getImageResult();
return create(result, AnimatedDrawableOptions.DEFAULTS);
} else {
throw new UnsupportedOperationException("Unrecognized image class: " + closeableImage);
}
}
/**
* Creates an {@link AnimatedDrawable} based on an {@link AnimatedImage}.
*
* @param animatedImageResult the result of the code
* @param options additional options
* @return a newly constructed {@link AnimatedDrawable}
*/
private AnimatedDrawable create(
AnimatedImageResult animatedImageResult,
AnimatedDrawableOptions options) {
AnimatedImage animatedImage = animatedImageResult.getImage();
Rect initialBounds = new Rect(0, 0, animatedImage.getWidth(), animatedImage.getHeight());
AnimatedDrawableBackend animatedDrawableBackend =
mAnimatedDrawableBackendProvider.get(animatedImageResult, initialBounds);
return createAnimatedDrawable(options, animatedDrawableBackend);
}
private AnimatedImageResult getImageIfCloseableAnimatedImage(CloseableImage image) {
if (image instanceof CloseableAnimatedImage) {
return ((CloseableAnimatedImage) image).getImageResult();
}
return null;
}
private AnimatedDrawable createAnimatedDrawable(
AnimatedDrawableOptions options,
AnimatedDrawableBackend animatedDrawableBackend) {
DisplayMetrics displayMetrics = mResources.getDisplayMetrics();
AnimatedDrawableDiagnostics animatedDrawableDiagnostics;
AnimatedDrawableCachingBackend animatedDrawableCachingBackend =
mAnimatedDrawableCachingBackendProvider.get(
animatedDrawableBackend,
options);
if (options.enableDebugging) {
animatedDrawableDiagnostics =
new AnimatedDrawableDiagnosticsImpl(mAnimatedDrawableUtil, displayMetrics);
} else {
animatedDrawableDiagnostics = AnimatedDrawableDiagnosticsNoop.getInstance();
}
return new AnimatedDrawable(
mScheduledExecutorServiceForUiThread,
animatedDrawableCachingBackend,
animatedDrawableDiagnostics,
mMonotonicClock);
}
}