/* * Copyright (C) 2017 Peng fei Pan <sky@xiaopan.me> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.xiaopan.sketch.drawable; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Animatable; import android.support.annotation.FloatRange; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.widget.MediaController; import java.io.InputStream; import java.nio.ByteBuffer; public interface SketchGifDrawable extends SketchDrawable, Animatable, MediaController.MediaPlayerControl { /** * Frees any memory allocated native way. * Operation is irreversible. After this call, nothing will be drawn. * This method is idempotent, subsequent calls have no effect. * Like {@link android.graphics.Bitmap#recycle()} this is an advanced call and * is invoked implicitly by finalizer. */ void recycle(); /** * @return true if drawable is recycled */ boolean isRecycled(); /** * Causes the animation to start over. * If rewinding input source fails then state is not affected. * This method is thread-safe. */ void reset(); /** * Returns GIF comment * * @return comment or null if there is no one defined in file */ String getComment(); /** * Returns loop count previously read from GIF's application extension block. * Defaults to 1 if there is no such extension. * * @return loop count, 0 means that animation is infinite */ int getLoopCount(); /** * Sets loop count of the animation. Loop count must be in range {@code <0 ,65535>} * * @param loopCount loop count, 0 means infinity */ void setLoopCount(@IntRange(from = 0, to = Character.MAX_VALUE) final int loopCount); /** * @return number of frames in GIF, at least one */ int getNumberOfFrames(); /** * Sets new animation speed factor.<br> * Note: If animation is in progress was already called) * then effects will be visible starting from the next frame. Duration of the currently rendered * frame is not affected. * * @param factor new speed factor, eg. 0.5f means half speed, 1.0f - normal, 2.0f - double speed * @throws IllegalArgumentException if factor<=0 */ void setSpeed(@FloatRange(from = 0, fromInclusive = false) final float factor); /** * Like but uses index of the frame instead of time. * If <code>frameIndex</code> exceeds number of frames, seek stops at the end, no exception is thrown. * * @param frameIndex index of the frame to seek to (zero based) * @throws IllegalArgumentException if <code>frameIndex</code><0 */ void seekToFrame(@IntRange(from = 0, to = Integer.MAX_VALUE) final int frameIndex); /** * Like {@link #seekToFrame(int)} but performs operation synchronously and returns that frame. * * @param frameIndex index of the frame to seek to (zero based) * @return frame at desired index * @throws IndexOutOfBoundsException if frameIndex<0 */ Bitmap seekToFrameAndGet(@IntRange(from = 0, to = Integer.MAX_VALUE) final int frameIndex); /** * Like but performs operation synchronously and returns that frame. * * @param position position to seek to in milliseconds * @return frame at desired position * @throws IndexOutOfBoundsException if position<0 */ Bitmap seekToPositionAndGet(@IntRange(from = 0, to = Integer.MAX_VALUE) final int position); /** * Returns the minimum number of bytes that can be used to store pixels of the single frame. * Returned value is the same for all the frames since it is based on the size of GIF screen. * <p>This method should not be used to calculate the memory usage of the bitmap. * Instead see {@link #getAllocationByteCount()}. * * @return the minimum number of bytes that can be used to store pixels of the single frame */ int getFrameByteCount(); /** * Returns size of the memory needed to store pixels of this object. It counts possible length of all frame buffers. * Returned value may be lower than amount of actually allocated memory if GIF uses dispose to previous method but frame requiring it * has never been needed yet. Returned value does not change during runtime. * * @return possible size of the memory needed to store pixels of this object */ long getAllocationByteCount(); /** * Returns the maximum possible size of the allocated memory used to store pixels and metadata of this object. * It counts length of all frame buffers. Returned value does not change over time. * * @return maximum possible size of the allocated memory needed to store metadata of this object */ long getMetadataAllocationByteCount(); /** * Returns length of the input source obtained at the opening time or -1 if * length cannot be determined. Returned value does not change during runtime. * If GifDrawable is constructed from {@link InputStream} -1 is always returned. * In case of byte array and {@link ByteBuffer} length is always known. * In other cases length -1 can be returned if length cannot be determined. * * @return number of bytes backed by input source or -1 if it is unknown */ long getInputSourceByteCount(); /** * Returns in pixels[] a copy of the data in the current frame. Each value is a packed int representing a {@link Color}. * * @param pixels the array to receive the frame's colors * @throws ArrayIndexOutOfBoundsException if the pixels array is too small to receive required number of pixels */ void getPixels(@NonNull int[] pixels); /** * Returns the {@link Color} at the specified location. Throws an exception * if x or y are out of bounds (negative or >= to the width or height * respectively). The returned color is a non-premultiplied ARGB value. * * @param x The x coordinate (0...width-1) of the pixel to return * @param y The y coordinate (0...height-1) of the pixel to return * @return The argb {@link Color} at the specified coordinate * @throws IllegalArgumentException if x, y exceed the drawable's bounds * @throws IllegalStateException if drawable is recycled */ int getPixel(int x, int y); /** * @return the paint used to render this drawable */ @NonNull Paint getPaint(); /** * Adds a new animation listener * * @param listener animation listener to be added, not null * @throws java.lang.NullPointerException if listener is null */ void addAnimationListener(@NonNull AnimationListener listener); /** * Removes an animation listener * * @param listener animation listener to be removed * @return true if listener collection has been modified */ boolean removeAnimationListener(AnimationListener listener); /** * Retrieves a copy of currently buffered frame. * * @return current frame */ Bitmap getCurrentFrame(); /** * Returns zero-based index of recently rendered frame in given loop or -1 when drawable is recycled. * * @return index of recently rendered frame or -1 when drawable is recycled */ int getCurrentFrameIndex(); /** * Returns zero-based index of currently played animation loop. If animation is infinite or * drawable is recycled 0 is returned. * * @return index of currently played animation loop */ int getCurrentLoop(); /** * Returns whether all animation loops has ended. If drawable is recycled false is returned. * * @return true if all animation loops has ended */ boolean isAnimationCompleted(); /** * Returns duration of the given frame (in milliseconds). If there is no data (no Graphics * Control Extension blocks or drawable is recycled) 0 is returned. * * @param index index of the frame * @return duration of the given frame in milliseconds * @throws IndexOutOfBoundsException if index < 0 or index >= number of frames */ int getFrameDuration(@IntRange(from = 0) final int index); /** * 跟随页面是否可见停止或播放gif * * @param userVisible 页面是否可见 * @param fromDisplayCompleted 当图片加载完毕,但是页面不可见时需要停留在第一帧 */ void followPageVisible(boolean userVisible, boolean fromDisplayCompleted); /** * Interface which can be used to run some code when particular animation event occurs. */ interface AnimationListener { /** * Called when a single loop of the animation is completed. * * @param loopNumber 0-based number of the completed loop, 0 for infinite animations */ void onAnimationCompleted(int loopNumber); } }