) {
46 | sprites.forEach { spritePool.release(it) }
47 | }
48 |
49 | open fun drawFrame(canvas : Canvas, frameIndex: Int, scaleType: ImageView.ScaleType) {
50 | scaleInfo.performScaleType(canvas.width.toFloat(),canvas.height.toFloat(), videoItem.videoSize.width.toFloat(), videoItem.videoSize.height.toFloat(), scaleType)
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationWithDynamicImageActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.ponycui_home.svgaplayer;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 |
8 | import com.opensource.svgaplayer.SVGADrawable;
9 | import com.opensource.svgaplayer.SVGADynamicEntity;
10 | import com.opensource.svgaplayer.SVGAImageView;
11 | import com.opensource.svgaplayer.SVGAParser;
12 | import com.opensource.svgaplayer.SVGAVideoEntity;
13 |
14 | import org.jetbrains.annotations.NotNull;
15 |
16 | import java.io.File;
17 | import java.net.MalformedURLException;
18 | import java.net.URL;
19 |
20 | public class AnimationWithDynamicImageActivity extends Activity {
21 |
22 | SVGAImageView animationView = null;
23 |
24 | @Override
25 | protected void onCreate(@Nullable Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | animationView = new SVGAImageView(this);
28 | animationView.setBackgroundColor(Color.GRAY);
29 | loadAnimation();
30 | setContentView(animationView);
31 | }
32 |
33 | private void loadAnimation() {
34 | try { // new URL needs try catch.
35 | SVGAParser parser = new SVGAParser(this);
36 | parser.decodeFromURL(new URL("https://github.com/yyued/SVGA-Samples/blob/master/kingset.svga?raw=true"), new SVGAParser.ParseCompletion() {
37 | @Override
38 | public void onComplete(@NotNull SVGAVideoEntity videoItem) {
39 | SVGADynamicEntity dynamicEntity = new SVGADynamicEntity();
40 | dynamicEntity.setDynamicImage("https://github.com/PonyCui/resources/blob/master/svga_replace_avatar.png?raw=true", "99"); // Here is the KEY implementation.
41 | SVGADrawable drawable = new SVGADrawable(videoItem, dynamicEntity);
42 | animationView.setImageDrawable(drawable);
43 | animationView.startAnimation();
44 | }
45 |
46 | @Override
47 | public void onError() {
48 |
49 | }
50 | }, null);
51 | } catch (MalformedURLException e) {
52 | e.printStackTrace();
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.ColorFilter
5 | import android.graphics.PixelFormat
6 | import android.graphics.drawable.Drawable
7 | import android.widget.ImageView
8 | import com.opensource.svgaplayer.drawer.SVGACanvasDrawer
9 |
10 | class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicEntity): Drawable() {
11 |
12 | constructor(videoItem: SVGAVideoEntity): this(videoItem, SVGADynamicEntity())
13 |
14 | var cleared = true
15 | internal set (value) {
16 | if (field == value) {
17 | return
18 | }
19 | field = value
20 | invalidateSelf()
21 | }
22 |
23 | var currentFrame = 0
24 | internal set (value) {
25 | if (field == value) {
26 | return
27 | }
28 | field = value
29 | invalidateSelf()
30 | }
31 |
32 | var scaleType: ImageView.ScaleType = ImageView.ScaleType.MATRIX
33 |
34 | private val drawer = SVGACanvasDrawer(videoItem, dynamicItem)
35 |
36 | override fun draw(canvas: Canvas?) {
37 | if (cleared) {
38 | return
39 | }
40 | canvas?.let {
41 | drawer.drawFrame(it,currentFrame, scaleType)
42 | }
43 | }
44 |
45 | override fun setAlpha(alpha: Int) {
46 |
47 | }
48 |
49 | override fun getOpacity(): Int {
50 | return PixelFormat.TRANSPARENT
51 | }
52 |
53 | override fun setColorFilter(colorFilter: ColorFilter?) {
54 |
55 | }
56 |
57 | fun resume() {
58 | videoItem.audioList.forEach { audio ->
59 | audio.playID?.let {
60 | if (SVGASoundManager.isInit()){
61 | SVGASoundManager.resume(it)
62 | }else{
63 | videoItem.soundPool?.resume(it)
64 | }
65 | }
66 | }
67 | }
68 |
69 | fun pause() {
70 | videoItem.audioList.forEach { audio ->
71 | audio.playID?.let {
72 | if (SVGASoundManager.isInit()){
73 | SVGASoundManager.pause(it)
74 | }else{
75 | videoItem.soundPool?.pause(it)
76 | }
77 | }
78 | }
79 | }
80 |
81 | fun stop() {
82 | videoItem.audioList.forEach { audio ->
83 | audio.playID?.let {
84 | if (SVGASoundManager.isInit()){
85 | SVGASoundManager.stop(it)
86 | }else{
87 | videoItem.soundPool?.stop(it)
88 | }
89 | }
90 | }
91 | }
92 |
93 | fun clear() {
94 | videoItem.audioList.forEach { audio ->
95 | audio.playID?.let {
96 | if (SVGASoundManager.isInit()){
97 | SVGASoundManager.stop(it)
98 | }else{
99 | videoItem.soundPool?.stop(it)
100 | }
101 | }
102 | audio.playID = null
103 | }
104 | videoItem.clear()
105 | }
106 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/utils/Pools.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer.utils
2 |
3 | /**
4 | * Helper class for creating pools of objects. An example use looks like this:
5 | *
6 | * public class MyPooledClass {
7 | *
8 | * private static final SynchronizedPool sPool =
9 | * new SynchronizedPool(10);
10 | *
11 | * public static MyPooledClass obtain() {
12 | * MyPooledClass instance = sPool.acquire();
13 | * return (instance != null) ? instance : new MyPooledClass();
14 | * }
15 | *
16 | * public void recycle() {
17 | * // Clear state if needed.
18 | * sPool.release(this);
19 | * }
20 | *
21 | * . . .
22 | * }
23 | *
24 | *
25 | */
26 | class Pools private constructor() {
27 |
28 | /**
29 | * Interface for managing a pool of objects.
30 | *
31 | * @param The pooled type.
32 | */
33 | interface Pool {
34 | /**
35 | * @return An instance from the pool if such, null otherwise.
36 | */
37 | fun acquire(): T?
38 |
39 | /**
40 | * Release an instance to the pool.
41 | *
42 | * @param instance The instance to release.
43 | * @return Whether the instance was put in the pool.
44 | *
45 | * @throws IllegalStateException If the instance is already in the pool.
46 | */
47 | fun release(instance: T): Boolean
48 | }
49 |
50 | /**
51 | * Simple (non-synchronized) pool of objects.
52 | *
53 | * @param maxPoolSize The max pool size.
54 | *
55 | * @throws IllegalArgumentException If the max pool size is less than zero.
56 | *
57 | * @param The pooled type.
58 | */
59 | open class SimplePool(maxPoolSize: Int) : Pool {
60 | private val mPool: Array
61 | private var mPoolSize = 0
62 |
63 | init {
64 | require(maxPoolSize > 0) { "The max pool size must be > 0" }
65 | mPool = arrayOfNulls(maxPoolSize)
66 | }
67 |
68 | @Suppress("UNCHECKED_CAST")
69 | override fun acquire(): T? {
70 | if (mPoolSize > 0) {
71 | val lastPooledIndex = mPoolSize - 1
72 | val instance = mPool[lastPooledIndex] as T?
73 | mPool[lastPooledIndex] = null
74 | mPoolSize--
75 | return instance
76 | }
77 | return null
78 | }
79 |
80 | override fun release(instance: T): Boolean {
81 | check(!isInPool(instance)) { "Already in the pool!" }
82 | if (mPoolSize < mPool.size) {
83 | mPool[mPoolSize] = instance
84 | mPoolSize++
85 | return true
86 | }
87 | return false
88 | }
89 |
90 | private fun isInPool(instance: T): Boolean {
91 | for (i in 0 until mPoolSize) {
92 | if (mPool[i] === instance) {
93 | return true
94 | }
95 | }
96 | return false
97 | }
98 |
99 | }
100 |
101 |
102 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/entities/SVGAVideoSpriteFrameEntity.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer.entities
2 |
3 | import android.graphics.Matrix
4 | import com.opensource.svgaplayer.proto.FrameEntity
5 | import com.opensource.svgaplayer.utils.SVGARect
6 |
7 | import org.json.JSONObject
8 |
9 | /**
10 | * Created by cuiminghui on 2016/10/17.
11 | */
12 | internal class SVGAVideoSpriteFrameEntity {
13 |
14 | var alpha: Double
15 | var layout = SVGARect(0.0, 0.0, 0.0, 0.0)
16 | var transform = Matrix()
17 | var maskPath: SVGAPathEntity? = null
18 | var shapes: List = listOf()
19 |
20 | constructor(obj: JSONObject) {
21 | this.alpha = obj.optDouble("alpha", 0.0)
22 | obj.optJSONObject("layout")?.let {
23 | layout = SVGARect(it.optDouble("x", 0.0), it.optDouble("y", 0.0), it.optDouble("width", 0.0), it.optDouble("height", 0.0))
24 | }
25 | obj.optJSONObject("transform")?.let {
26 | val arr = FloatArray(9)
27 | val a = it.optDouble("a", 1.0)
28 | val b = it.optDouble("b", 0.0)
29 | val c = it.optDouble("c", 0.0)
30 | val d = it.optDouble("d", 1.0)
31 | val tx = it.optDouble("tx", 0.0)
32 | val ty = it.optDouble("ty", 0.0)
33 | arr[0] = a.toFloat()
34 | arr[1] = c.toFloat()
35 | arr[2] = tx.toFloat()
36 | arr[3] = b.toFloat()
37 | arr[4] = d.toFloat()
38 | arr[5] = ty.toFloat()
39 | arr[6] = 0.0.toFloat()
40 | arr[7] = 0.0.toFloat()
41 | arr[8] = 1.0.toFloat()
42 | transform.setValues(arr)
43 | }
44 | obj.optString("clipPath")?.let { d ->
45 | if (d.isNotEmpty()) {
46 | maskPath = SVGAPathEntity(d)
47 | }
48 | }
49 | obj.optJSONArray("shapes")?.let {
50 | val mutableList: MutableList = mutableListOf()
51 | for (i in 0 until it.length()) {
52 | it.optJSONObject(i)?.let {
53 | mutableList.add(SVGAVideoShapeEntity(it))
54 | }
55 | }
56 | shapes = mutableList.toList()
57 | }
58 | }
59 |
60 | constructor(obj: FrameEntity) {
61 | this.alpha = (obj.alpha ?: 0.0f).toDouble()
62 | obj.layout?.let {
63 | this.layout = SVGARect((it.x ?: 0.0f).toDouble(), (it.y
64 | ?: 0.0f).toDouble(), (it.width ?: 0.0f).toDouble(), (it.height
65 | ?: 0.0f).toDouble())
66 | }
67 | obj.transform?.let {
68 | val arr = FloatArray(9)
69 | val a = it.a ?: 1.0f
70 | val b = it.b ?: 0.0f
71 | val c = it.c ?: 0.0f
72 | val d = it.d ?: 1.0f
73 | val tx = it.tx ?: 0.0f
74 | val ty = it.ty ?: 0.0f
75 | arr[0] = a
76 | arr[1] = c
77 | arr[2] = tx
78 | arr[3] = b
79 | arr[4] = d
80 | arr[5] = ty
81 | arr[6] = 0.0f
82 | arr[7] = 0.0f
83 | arr[8] = 1.0f
84 | transform.setValues(arr)
85 | }
86 | obj.clipPath?.takeIf { it.isNotEmpty() }?.let {
87 | maskPath = SVGAPathEntity(it)
88 | }
89 | this.shapes = obj.shapes.map {
90 | return@map SVGAVideoShapeEntity(it)
91 | }
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.ponycui_home.svgaplayer;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.util.Log;
8 | import android.view.View;
9 |
10 | import com.opensource.svgaplayer.SVGAImageView;
11 | import com.opensource.svgaplayer.SVGAParser;
12 | import com.opensource.svgaplayer.SVGASoundManager;
13 | import com.opensource.svgaplayer.SVGAVideoEntity;
14 | import com.opensource.svgaplayer.utils.log.SVGALogger;
15 |
16 | import org.jetbrains.annotations.NotNull;
17 |
18 | import java.io.File;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | public class AnimationFromAssetsActivity extends Activity {
23 |
24 | int currentIndex = 0;
25 | SVGAImageView animationView = null;
26 |
27 | @Override
28 | protected void onCreate(@Nullable Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | animationView = new SVGAImageView(this);
31 | animationView.setBackgroundColor(Color.BLACK);
32 | animationView.setOnClickListener(new View.OnClickListener() {
33 | @Override
34 | public void onClick(View view) {
35 | animationView.stepToFrame(currentIndex++, false);
36 | }
37 | });
38 | SVGALogger.INSTANCE.setLogEnabled(true);
39 | SVGASoundManager.INSTANCE.init();
40 | loadAnimation();
41 | setContentView(animationView);
42 | }
43 |
44 | private void loadAnimation() {
45 | SVGAParser svgaParser = SVGAParser.Companion.shareParser();
46 | // String name = this.randomSample();
47 | //asset jojo_audio.svga cannot callback
48 | String name = "mp3_to_long.svga";
49 | Log.d("SVGA", "## name " + name);
50 | svgaParser.setFrameSize(100, 100);
51 | svgaParser.decodeFromAssets(name, new SVGAParser.ParseCompletion() {
52 | @Override
53 | public void onComplete(@NotNull SVGAVideoEntity videoItem) {
54 | Log.e("zzzz", "onComplete: ");
55 | animationView.setVideoItem(videoItem);
56 | animationView.stepToFrame(0, true);
57 | }
58 |
59 | @Override
60 | public void onError() {
61 | Log.e("zzzz", "onComplete: ");
62 | }
63 |
64 | }, null);
65 | }
66 |
67 | private ArrayList samples = new ArrayList();
68 |
69 | private String randomSample() {
70 | if (samples.size() == 0) {
71 | samples.add("750x80.svga");
72 | samples.add("alarm.svga");
73 | samples.add("angel.svga");
74 | samples.add("Castle.svga");
75 | samples.add("EmptyState.svga");
76 | samples.add("Goddess.svga");
77 | samples.add("gradientBorder.svga");
78 | samples.add("heartbeat.svga");
79 | samples.add("matteBitmap.svga");
80 | samples.add("matteBitmap_1.x.svga");
81 | samples.add("matteRect.svga");
82 | samples.add("MerryChristmas.svga");
83 | samples.add("posche.svga");
84 | samples.add("Rocket.svga");
85 | samples.add("rose.svga");
86 | samples.add("rose_2.0.0.svga");
87 | }
88 | return samples.get((int) Math.floor(Math.random() * samples.size()));
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/SVGACache.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer
2 |
3 | import android.content.Context
4 | import com.opensource.svgaplayer.utils.log.LogUtils
5 | import java.io.File
6 | import java.net.URL
7 | import java.security.MessageDigest
8 |
9 | /**
10 | * SVGA 缓存管理
11 | */
12 | object SVGACache {
13 | enum class Type {
14 | DEFAULT,
15 | FILE
16 | }
17 |
18 | private const val TAG = "SVGACache"
19 | private var type: Type = Type.DEFAULT
20 | private var cacheDir: String = "/"
21 | get() {
22 | if (field != "/") {
23 | val dir = File(field)
24 | if (!dir.exists()) {
25 | dir.mkdirs()
26 | }
27 | }
28 | return field
29 | }
30 |
31 |
32 | fun onCreate(context: Context?) {
33 | onCreate(context, Type.DEFAULT)
34 | }
35 |
36 | fun onCreate(context: Context?, type: Type) {
37 | if (isInitialized()) return
38 | context ?: return
39 | cacheDir = "${context.cacheDir.absolutePath}/svga/"
40 | File(cacheDir).takeIf { !it.exists() }?.mkdirs()
41 | this.type = type
42 | }
43 |
44 | /**
45 | * 清理缓存
46 | */
47 | fun clearCache() {
48 | if (!isInitialized()) {
49 | LogUtils.error(TAG, "SVGACache is not init!")
50 | return
51 | }
52 | SVGAParser.threadPoolExecutor.execute {
53 | clearDir(cacheDir)
54 | LogUtils.info(TAG, "Clear svga cache done!")
55 | }
56 | }
57 |
58 | // 清除目录下的所有文件
59 | internal fun clearDir(path: String) {
60 | try {
61 | val dir = File(path)
62 | dir.takeIf { it.exists() }?.let { parentDir ->
63 | parentDir.listFiles()?.forEach { file ->
64 | if (!file.exists()) {
65 | return@forEach
66 | }
67 | if (file.isDirectory) {
68 | clearDir(file.absolutePath)
69 | }
70 | file.delete()
71 | }
72 | }
73 | } catch (e: Exception) {
74 | LogUtils.error(TAG, "Clear svga cache path: $path fail", e)
75 | }
76 | }
77 |
78 | fun isInitialized(): Boolean {
79 | return "/" != cacheDir && File(cacheDir).exists()
80 | }
81 |
82 | fun isDefaultCache(): Boolean = type == Type.DEFAULT
83 |
84 | fun isCached(cacheKey: String): Boolean {
85 | return if (isDefaultCache()) {
86 | buildCacheDir(cacheKey)
87 | } else {
88 | buildSvgaFile(
89 | cacheKey
90 | )
91 | }.exists()
92 | }
93 |
94 | fun buildCacheKey(str: String): String {
95 | val messageDigest = MessageDigest.getInstance("MD5")
96 | messageDigest.update(str.toByteArray(charset("UTF-8")))
97 | val digest = messageDigest.digest()
98 | var sb = ""
99 | for (b in digest) {
100 | sb += String.format("%02x", b)
101 | }
102 | return sb
103 | }
104 |
105 | fun buildCacheKey(url: URL): String = buildCacheKey(url.toString())
106 |
107 | fun buildCacheDir(cacheKey: String): File {
108 | return File("$cacheDir$cacheKey/")
109 | }
110 |
111 | fun buildSvgaFile(cacheKey: String): File {
112 | return File("$cacheDir$cacheKey.svga")
113 | }
114 |
115 | fun buildAudioFile(audio: String): File {
116 | return File("$cacheDir$audio.mp3")
117 | }
118 |
119 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/entities/SVGAPathEntity.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer.entities
2 |
3 | import android.graphics.Path
4 | import com.opensource.svgaplayer.utils.SVGAPoint
5 | import java.util.*
6 |
7 | private val VALID_METHODS: Set = setOf("M", "L", "H", "V", "C", "S", "Q", "R", "A", "Z", "m", "l", "h", "v", "c", "s", "q", "r", "a", "z")
8 |
9 | class SVGAPathEntity(originValue: String) {
10 |
11 | private val replacedValue: String = if (originValue.contains(",")) originValue.replace(",", " ") else originValue
12 |
13 | private var cachedPath: Path? = null
14 |
15 | fun buildPath(toPath: Path) {
16 | cachedPath?.let {
17 | toPath.set(it)
18 | return
19 | }
20 | val cachedPath = Path()
21 | val segments = StringTokenizer(this.replacedValue, "MLHVCSQRAZmlhvcsqraz", true)
22 | var currentMethod = ""
23 | while (segments.hasMoreTokens()) {
24 | val segment = segments.nextToken()
25 | if (segment.isEmpty()) { continue }
26 | if (VALID_METHODS.contains(segment)) {
27 | currentMethod = segment
28 | if (currentMethod == "Z" || currentMethod == "z") { operate(cachedPath, currentMethod, StringTokenizer("", "")) }
29 | }
30 | else {
31 | operate(cachedPath, currentMethod, StringTokenizer(segment, " "))
32 | }
33 | }
34 | this.cachedPath = cachedPath
35 | toPath.set(cachedPath)
36 | }
37 |
38 | private fun operate(finalPath: Path, method: String, args: StringTokenizer) {
39 | var x0 = 0.0f
40 | var y0 = 0.0f
41 | var x1 = 0.0f
42 | var y1 = 0.0f
43 | var x2 = 0.0f
44 | var y2 = 0.0f
45 | try {
46 | var index = 0
47 | while (args.hasMoreTokens()) {
48 | val s = args.nextToken()
49 | if (s.isEmpty()) {continue}
50 | if (index == 0) { x0 = s.toFloat() }
51 | if (index == 1) { y0 = s.toFloat() }
52 | if (index == 2) { x1 = s.toFloat() }
53 | if (index == 3) { y1 = s.toFloat() }
54 | if (index == 4) { x2 = s.toFloat() }
55 | if (index == 5) { y2 = s.toFloat() }
56 | index++
57 | }
58 | } catch (e: Exception) {}
59 | var currentPoint = SVGAPoint(0.0f, 0.0f, 0.0f)
60 | if (method == "M") {
61 | finalPath.moveTo(x0, y0)
62 | currentPoint = SVGAPoint(x0, y0, 0.0f)
63 | } else if (method == "m") {
64 | finalPath.rMoveTo(x0, y0)
65 | currentPoint = SVGAPoint(currentPoint.x + x0, currentPoint.y + y0, 0.0f)
66 | }
67 | if (method == "L") {
68 | finalPath.lineTo(x0, y0)
69 | } else if (method == "l") {
70 | finalPath.rLineTo(x0, y0)
71 | }
72 | if (method == "C") {
73 | finalPath.cubicTo(x0, y0, x1, y1, x2, y2)
74 | } else if (method == "c") {
75 | finalPath.rCubicTo(x0, y0, x1, y1, x2, y2)
76 | }
77 | if (method == "Q") {
78 | finalPath.quadTo(x0, y0, x1, y1)
79 | } else if (method == "q") {
80 | finalPath.rQuadTo(x0, y0, x1, y1)
81 | }
82 | if (method == "H") {
83 | finalPath.lineTo(x0, currentPoint.y)
84 | } else if (method == "h") {
85 | finalPath.rLineTo(x0, 0f)
86 | }
87 | if (method == "V") {
88 | finalPath.lineTo(currentPoint.x, x0)
89 | } else if (method == "v") {
90 | finalPath.rLineTo(0f, x0)
91 | }
92 | if (method == "Z") {
93 | finalPath.close()
94 | }
95 | else if (method == "z") {
96 | finalPath.close()
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ponycui_home/svgaplayer/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.ponycui_home.svgaplayer;
2 |
3 | import android.content.Intent;
4 | import android.database.DataSetObserver;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.view.Gravity;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.LinearLayout;
13 | import android.widget.ListAdapter;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 |
17 | import com.opensource.svgaplayer.SVGAParser;
18 | import com.opensource.svgaplayer.utils.log.SVGALogger;
19 |
20 | import java.util.ArrayList;
21 |
22 | class SampleItem {
23 |
24 | String title;
25 | Intent intent;
26 |
27 | public SampleItem(String title, Intent intent) {
28 | this.title = title;
29 | this.intent = intent;
30 | }
31 |
32 | }
33 |
34 | public class MainActivity extends AppCompatActivity {
35 |
36 | ListView listView;
37 | ArrayList items = new ArrayList();
38 |
39 | @Override
40 | protected void onCreate(@Nullable Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | this.setupData();
43 | this.setupListView();
44 | this.setupSVGAParser();
45 | this.setupLogger();
46 | setContentView(listView);
47 | }
48 |
49 | void setupData() {
50 | this.items.add(new SampleItem("Animation From Assets", new Intent(this, AnimationFromAssetsActivity.class)));
51 | this.items.add(new SampleItem("Animation From Network", new Intent(this, AnimationFromNetworkActivity.class)));
52 | this.items.add(new SampleItem("Animation From Layout XML", new Intent(this, AnimationFromLayoutActivity.class)));
53 | this.items.add(new SampleItem("Animation With Dynamic Image", new Intent(this, AnimationWithDynamicImageActivity.class)));
54 | this.items.add(new SampleItem("Animation With Dynamic Click", new Intent(this, AnimationFromClickActivity.class)));
55 | }
56 |
57 | void setupListView() {
58 | this.listView = new ListView(this);
59 | this.listView.setAdapter(new ListAdapter() {
60 | @Override
61 | public boolean areAllItemsEnabled() {
62 | return false;
63 | }
64 |
65 | @Override
66 | public boolean isEnabled(int i) {
67 | return false;
68 | }
69 |
70 | @Override
71 | public void registerDataSetObserver(DataSetObserver dataSetObserver) {
72 |
73 | }
74 |
75 | @Override
76 | public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
77 |
78 | }
79 |
80 | @Override
81 | public int getCount() {
82 | return MainActivity.this.items.size();
83 | }
84 |
85 | @Override
86 | public Object getItem(int i) {
87 | return null;
88 | }
89 |
90 | @Override
91 | public long getItemId(int i) {
92 | return i;
93 | }
94 |
95 | @Override
96 | public boolean hasStableIds() {
97 | return false;
98 | }
99 |
100 | @Override
101 | public View getView(final int i, View view, ViewGroup viewGroup) {
102 | LinearLayout linearLayout = new LinearLayout(MainActivity.this);
103 | TextView textView = new TextView(MainActivity.this);
104 | textView.setOnClickListener(new View.OnClickListener() {
105 | @Override
106 | public void onClick(View view) {
107 | MainActivity.this.startActivity(MainActivity.this.items.get(i).intent);
108 | }
109 | });
110 | textView.setText(MainActivity.this.items.get(i).title);
111 | textView.setTextSize(24);
112 | textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
113 | linearLayout.addView(textView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (55 * getResources().getDisplayMetrics().density)));
114 | return linearLayout;
115 | }
116 |
117 | @Override
118 | public int getItemViewType(int i) {
119 | return 1;
120 | }
121 |
122 | @Override
123 | public int getViewTypeCount() {
124 | return 1;
125 | }
126 |
127 | @Override
128 | public boolean isEmpty() {
129 | return false;
130 | }
131 | });
132 | this.listView.setBackgroundColor(Color.WHITE);
133 | }
134 |
135 | void setupSVGAParser() {
136 | SVGAParser.Companion.shareParser().init(this);
137 | }
138 |
139 | private void setupLogger() {
140 | SVGALogger.INSTANCE.setLogEnabled(true);
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/utils/SVGAScaleInfo.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer.utils
2 |
3 | import android.widget.ImageView
4 |
5 | /**
6 | * Created by ubt on 2018/1/19.
7 | */
8 | class SVGAScaleInfo {
9 |
10 | var tranFx : Float = 0.0f
11 | var tranFy : Float = 0.0f
12 | var scaleFx : Float = 1.0f
13 | var scaleFy : Float = 1.0f
14 | var ratio = 1.0f
15 | var ratioX = false
16 |
17 | private fun resetVar(){
18 | tranFx = 0.0f
19 | tranFy = 0.0f
20 | scaleFx = 1.0f
21 | scaleFy = 1.0f
22 | ratio = 1.0f
23 | ratioX = false
24 | }
25 |
26 | fun performScaleType(canvasWidth : Float, canvasHeight: Float, videoWidth : Float, videoHeight : Float, scaleType: ImageView.ScaleType) {
27 | if (canvasWidth == 0.0f || canvasHeight == 0.0f || videoWidth == 0.0f || videoHeight == 0.0f) {
28 | return
29 | }
30 |
31 | resetVar()
32 | val canW_vidW_f = (canvasWidth - videoWidth) / 2.0f
33 | val canH_vidH_f = (canvasHeight - videoHeight) / 2.0f
34 |
35 | val videoRatio = videoWidth / videoHeight
36 | val canvasRatio = canvasWidth / canvasHeight
37 |
38 | val canH_d_vidH = canvasHeight / videoHeight
39 | val canW_d_vidW = canvasWidth / videoWidth
40 |
41 | when (scaleType) {
42 | ImageView.ScaleType.CENTER -> {
43 | tranFx = canW_vidW_f
44 | tranFy = canH_vidH_f
45 | }
46 | ImageView.ScaleType.CENTER_CROP -> {
47 | if (videoRatio > canvasRatio) {
48 | ratio = canH_d_vidH
49 | ratioX = false
50 | scaleFx = canH_d_vidH
51 | scaleFy = canH_d_vidH
52 | tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
53 | }
54 | else {
55 | ratio = canW_d_vidW
56 | ratioX = true
57 | scaleFx = canW_d_vidW
58 | scaleFy = canW_d_vidW
59 | tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
60 | }
61 | }
62 | ImageView.ScaleType.CENTER_INSIDE -> {
63 | if (videoWidth < canvasWidth && videoHeight < canvasHeight) {
64 | tranFx = canW_vidW_f
65 | tranFy = canH_vidH_f
66 | }
67 | else {
68 | if (videoRatio > canvasRatio) {
69 | ratio = canW_d_vidW
70 | ratioX = true
71 | scaleFx = canW_d_vidW
72 | scaleFy = canW_d_vidW
73 | tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
74 |
75 | }
76 | else {
77 | ratio = canH_d_vidH
78 | ratioX = false
79 | scaleFx = canH_d_vidH
80 | scaleFy = canH_d_vidH
81 | tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
82 | }
83 | }
84 | }
85 | ImageView.ScaleType.FIT_CENTER -> {
86 | if (videoRatio > canvasRatio) {
87 | ratio = canW_d_vidW
88 | ratioX = true
89 | scaleFx = canW_d_vidW
90 | scaleFy = canW_d_vidW
91 | tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
92 | }
93 | else {
94 | ratio = canH_d_vidH
95 | ratioX = false
96 | scaleFx = canH_d_vidH
97 | scaleFy = canH_d_vidH
98 | tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
99 | }
100 | }
101 | ImageView.ScaleType.FIT_START -> {
102 | if (videoRatio > canvasRatio) {
103 | ratio = canW_d_vidW
104 | ratioX = true
105 | scaleFx = canW_d_vidW
106 | scaleFy = canW_d_vidW
107 | }
108 | else {
109 | ratio = canH_d_vidH
110 | ratioX = false
111 | scaleFx = canH_d_vidH
112 | scaleFy = canH_d_vidH
113 | }
114 | }
115 | ImageView.ScaleType.FIT_END -> {
116 | if (videoRatio > canvasRatio) {
117 | ratio = canW_d_vidW
118 | ratioX = true
119 | scaleFx = canW_d_vidW
120 | scaleFy = canW_d_vidW
121 | tranFy= canvasHeight - videoHeight * (canW_d_vidW)
122 | }
123 | else {
124 | ratio = canH_d_vidH
125 | ratioX = false
126 | scaleFx = canH_d_vidH
127 | scaleFy = canH_d_vidH
128 | tranFx = canvasWidth - videoWidth * (canH_d_vidH)
129 | }
130 | }
131 | ImageView.ScaleType.FIT_XY -> {
132 | ratio = Math.max(canW_d_vidW, canH_d_vidH)
133 | ratioX = canW_d_vidW > canH_d_vidH
134 | scaleFx = canW_d_vidW
135 | scaleFy = canH_d_vidH
136 | }
137 | else -> {
138 | ratio = canW_d_vidW
139 | ratioX = true
140 | scaleFx = canW_d_vidW
141 | scaleFy = canW_d_vidW
142 | }
143 | }
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | yes | $ANDROID_HOME/tools/bin/sdkmanager "build-tools;28.0.3"
3 |
4 | ##############################################################################
5 | ##
6 | ## Gradle start up script for UN*X
7 | ##
8 | ##############################################################################
9 |
10 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
11 | DEFAULT_JVM_OPTS=""
12 |
13 | APP_NAME="Gradle"
14 | APP_BASE_NAME=`basename "$0"`
15 |
16 | # Use the maximum available, or set MAX_FD != -1 to use that value.
17 | MAX_FD="maximum"
18 |
19 | warn ( ) {
20 | echo "$*"
21 | }
22 |
23 | die ( ) {
24 | echo
25 | echo "$*"
26 | echo
27 | exit 1
28 | }
29 |
30 | # OS specific support (must be 'true' or 'false').
31 | cygwin=false
32 | msys=false
33 | darwin=false
34 | case "`uname`" in
35 | CYGWIN* )
36 | cygwin=true
37 | ;;
38 | Darwin* )
39 | darwin=true
40 | ;;
41 | MINGW* )
42 | msys=true
43 | ;;
44 | esac
45 |
46 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
47 | if $cygwin ; then
48 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
49 | fi
50 |
51 | # Attempt to set APP_HOME
52 | # Resolve links: $0 may be a link
53 | PRG="$0"
54 | # Need this for relative symlinks.
55 | while [ -h "$PRG" ] ; do
56 | ls=`ls -ld "$PRG"`
57 | link=`expr "$ls" : '.*-> \(.*\)$'`
58 | if expr "$link" : '/.*' > /dev/null; then
59 | PRG="$link"
60 | else
61 | PRG=`dirname "$PRG"`"/$link"
62 | fi
63 | done
64 | SAVED="`pwd`"
65 | cd "`dirname \"$PRG\"`/" >&-
66 | APP_HOME="`pwd -P`"
67 | cd "$SAVED" >&-
68 |
69 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
70 |
71 | # Determine the Java command to use to start the JVM.
72 | if [ -n "$JAVA_HOME" ] ; then
73 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
74 | # IBM's JDK on AIX uses strange locations for the executables
75 | JAVACMD="$JAVA_HOME/jre/sh/java"
76 | else
77 | JAVACMD="$JAVA_HOME/bin/java"
78 | fi
79 | if [ ! -x "$JAVACMD" ] ; then
80 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
81 |
82 | Please set the JAVA_HOME variable in your environment to match the
83 | location of your Java installation."
84 | fi
85 | else
86 | JAVACMD="java"
87 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
88 |
89 | Please set the JAVA_HOME variable in your environment to match the
90 | location of your Java installation."
91 | fi
92 |
93 | # Increase the maximum file descriptors if we can.
94 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
95 | MAX_FD_LIMIT=`ulimit -H -n`
96 | if [ $? -eq 0 ] ; then
97 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
98 | MAX_FD="$MAX_FD_LIMIT"
99 | fi
100 | ulimit -n $MAX_FD
101 | if [ $? -ne 0 ] ; then
102 | warn "Could not set maximum file descriptor limit: $MAX_FD"
103 | fi
104 | else
105 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
106 | fi
107 | fi
108 |
109 | # For Darwin, add options to specify how the application appears in the dock
110 | if $darwin; then
111 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
112 | fi
113 |
114 | # For Cygwin, switch paths to Windows format before running java
115 | if $cygwin ; then
116 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
117 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
118 |
119 | # We build the pattern for arguments to be converted via cygpath
120 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
121 | SEP=""
122 | for dir in $ROOTDIRSRAW ; do
123 | ROOTDIRS="$ROOTDIRS$SEP$dir"
124 | SEP="|"
125 | done
126 | OURCYGPATTERN="(^($ROOTDIRS))"
127 | # Add a user-defined pattern to the cygpath arguments
128 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
129 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
130 | fi
131 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
132 | i=0
133 | for arg in "$@" ; do
134 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
135 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
136 |
137 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
138 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
139 | else
140 | eval `echo args$i`="\"$arg\""
141 | fi
142 | i=$((i+1))
143 | done
144 | case $i in
145 | (0) set -- ;;
146 | (1) set -- "$args0" ;;
147 | (2) set -- "$args0" "$args1" ;;
148 | (3) set -- "$args0" "$args1" "$args2" ;;
149 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
150 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
151 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
152 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
153 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
154 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
155 | esac
156 | fi
157 |
158 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
159 | function splitJvmOpts() {
160 | JVM_OPTS=("$@")
161 | }
162 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
163 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
164 |
165 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
166 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/SVGADynamicEntity.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer
2 |
3 | import android.graphics.Bitmap
4 | import android.graphics.BitmapFactory
5 | import android.graphics.Canvas
6 | import android.text.BoringLayout
7 | import android.text.StaticLayout
8 | import android.text.TextPaint
9 | import java.net.HttpURLConnection
10 | import java.net.URL
11 |
12 | /**
13 | * Created by cuiminghui on 2017/3/30.
14 | */
15 | class SVGADynamicEntity {
16 |
17 | internal var dynamicHidden: HashMap = hashMapOf()
18 |
19 | internal var dynamicImage: HashMap = hashMapOf()
20 |
21 | internal var dynamicText: HashMap = hashMapOf()
22 |
23 | internal var dynamicTextPaint: HashMap = hashMapOf()
24 |
25 | internal var dynamicStaticLayoutText: HashMap = hashMapOf()
26 |
27 | internal var dynamicBoringLayoutText: HashMap = hashMapOf()
28 |
29 | internal var dynamicDrawer: HashMap Boolean> = hashMapOf()
30 |
31 | //点击事件回调map
32 | internal var mClickMap : HashMap = hashMapOf()
33 | internal var dynamicIClickArea: HashMap = hashMapOf()
34 |
35 | internal var dynamicDrawerSized: HashMap Boolean> = hashMapOf()
36 |
37 |
38 | internal var isTextDirty = false
39 |
40 | fun setHidden(value: Boolean, forKey: String) {
41 | this.dynamicHidden.put(forKey, value)
42 | }
43 |
44 | fun setDynamicImage(bitmap: Bitmap, forKey: String) {
45 | this.dynamicImage.put(forKey, bitmap)
46 | }
47 |
48 | fun setDynamicImage(url: String, forKey: String) {
49 | val handler = android.os.Handler()
50 | SVGAParser.threadPoolExecutor.execute {
51 | (URL(url).openConnection() as? HttpURLConnection)?.let {
52 | try {
53 | it.connectTimeout = 20 * 1000
54 | it.requestMethod = "GET"
55 | it.connect()
56 | it.inputStream.use { stream ->
57 | BitmapFactory.decodeStream(stream)?.let {
58 | handler.post { setDynamicImage(it, forKey) }
59 | }
60 | }
61 | } catch (e: Exception) {
62 | e.printStackTrace()
63 | } finally {
64 | try {
65 | it.disconnect()
66 | } catch (disconnectException: Throwable) {
67 | // ignored here
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
74 | fun setDynamicText(text: String, textPaint: TextPaint, forKey: String) {
75 | this.isTextDirty = true
76 | this.dynamicText.put(forKey, text)
77 | this.dynamicTextPaint.put(forKey, textPaint)
78 | }
79 |
80 | fun setDynamicText(layoutText: StaticLayout, forKey: String) {
81 | this.isTextDirty = true
82 | this.dynamicStaticLayoutText.put(forKey, layoutText)
83 | }
84 |
85 | fun setDynamicText(layoutText: BoringLayout, forKey: String) {
86 | this.isTextDirty = true
87 | BoringLayout.isBoring(layoutText.text,layoutText.paint)?.let {
88 | this.dynamicBoringLayoutText.put(forKey,layoutText)
89 | }
90 | }
91 |
92 | fun setDynamicDrawer(drawer: (canvas: Canvas, frameIndex: Int) -> Boolean, forKey: String) {
93 | this.dynamicDrawer.put(forKey, drawer)
94 | }
95 |
96 | fun setClickArea(clickKey: List) {
97 | for(itemKey in clickKey){
98 | dynamicIClickArea.put(itemKey,object : IClickAreaListener {
99 | override fun onResponseArea(key: String, x0: Int, y0: Int, x1: Int, y1: Int) {
100 | mClickMap.let {
101 | if(it.get(key) == null){
102 | it.put(key, intArrayOf(x0,y0,x1,y1))
103 | }else{
104 | it.get(key)?.let {
105 | it[0] = x0
106 | it[1] = y0
107 | it[2] = x1
108 | it[3] = y1
109 | }
110 | }
111 | }
112 | }
113 | })
114 | }
115 | }
116 |
117 | fun setClickArea(clickKey: String) {
118 | dynamicIClickArea.put(clickKey, object : IClickAreaListener {
119 | override fun onResponseArea(key: String, x0: Int, y0: Int, x1: Int, y1: Int) {
120 | mClickMap.let {
121 | if (it.get(key) == null) {
122 | it.put(key, intArrayOf(x0, y0, x1, y1))
123 | } else {
124 | it.get(key)?.let {
125 | it[0] = x0
126 | it[1] = y0
127 | it[2] = x1
128 | it[3] = y1
129 | }
130 | }
131 | }
132 | }
133 | })
134 | }
135 |
136 | fun setDynamicDrawerSized(drawer: (canvas: Canvas, frameIndex: Int, width: Int, height: Int) -> Boolean, forKey: String) {
137 | this.dynamicDrawerSized.put(forKey, drawer)
138 | }
139 |
140 | fun clearDynamicObjects() {
141 | this.isTextDirty = true
142 | this.dynamicHidden.clear()
143 | this.dynamicImage.clear()
144 | this.dynamicText.clear()
145 | this.dynamicTextPaint.clear()
146 | this.dynamicStaticLayoutText.clear()
147 | this.dynamicBoringLayoutText.clear()
148 | this.dynamicDrawer.clear()
149 | this.dynamicIClickArea.clear()
150 | this.mClickMap.clear()
151 | this.dynamicDrawerSized.clear()
152 | }
153 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/SVGASoundManager.kt:
--------------------------------------------------------------------------------
1 | package com.opensource.svgaplayer
2 |
3 | /**
4 | * @author Devin
5 | *
6 | * Created on 2/24/21.
7 | */
8 | import android.media.AudioAttributes
9 | import android.media.AudioManager
10 | import android.media.SoundPool
11 | import android.os.Build
12 | import com.opensource.svgaplayer.utils.log.LogUtils
13 | import java.io.FileDescriptor
14 |
15 | /**
16 | * Author : llk
17 | * Time : 2020/10/24
18 | * Description : svga 音频加载管理类
19 | * 将 SoundPool 抽取到单例里边,规避 load 资源之后不回调 onLoadComplete 的问题。
20 | *
21 | * 需要对 SVGASoundManager 进行初始化
22 | *
23 | * 相关文章:Android SoundPool 崩溃问题研究
24 | * https://zhuanlan.zhihu.com/p/29985198
25 | */
26 | object SVGASoundManager {
27 |
28 | private val TAG = SVGASoundManager::class.java.simpleName
29 |
30 | private var soundPool: SoundPool? = null
31 |
32 | private val soundCallBackMap: MutableMap = mutableMapOf()
33 |
34 | /**
35 | * 音量设置,范围在 [0, 1] 之间
36 | */
37 | private var volume: Float = 1f
38 |
39 | /**
40 | * 音频回调
41 | */
42 | internal interface SVGASoundCallBack {
43 |
44 | // 音量发生变化
45 | fun onVolumeChange(value: Float)
46 |
47 | // 音频加载完成
48 | fun onComplete()
49 | }
50 |
51 | fun init() {
52 | init(20)
53 | }
54 |
55 | fun init(maxStreams: Int) {
56 | LogUtils.debug(TAG, "**************** init **************** $maxStreams")
57 | if (soundPool != null) {
58 | return
59 | }
60 | soundPool = getSoundPool(maxStreams)
61 | soundPool?.setOnLoadCompleteListener { _, soundId, status ->
62 | LogUtils.debug(TAG, "SoundPool onLoadComplete soundId=$soundId status=$status")
63 | if (status == 0) { //加载该声音成功
64 | if (soundCallBackMap.containsKey(soundId)) {
65 | soundCallBackMap[soundId]?.onComplete()
66 | }
67 | }
68 | }
69 | }
70 |
71 | fun release() {
72 | LogUtils.debug(TAG, "**************** release ****************")
73 | if (soundCallBackMap.isNotEmpty()) {
74 | soundCallBackMap.clear()
75 | }
76 | }
77 |
78 | /**
79 | * 根据当前播放实体,设置音量
80 | *
81 | * @param volume 范围在 [0, 1]
82 | * @param entity 根据需要控制对应 entity 音量大小,若为空则控制所有正在播放的音频音量
83 | */
84 | fun setVolume(volume: Float, entity: SVGAVideoEntity? = null) {
85 | if (!checkInit()) {
86 | return
87 | }
88 |
89 | if (volume < 0f || volume > 1f) {
90 | LogUtils.error(TAG, "The volume level is in the range of 0 to 1 ")
91 | return
92 | }
93 |
94 | if (entity == null) {
95 | this.volume = volume
96 | val iterator = soundCallBackMap.entries.iterator()
97 | while (iterator.hasNext()) {
98 | val e = iterator.next()
99 | e.value.onVolumeChange(volume)
100 | }
101 | return
102 | }
103 |
104 | val soundPool = soundPool ?: return
105 |
106 | entity.audioList.forEach { audio ->
107 | val streamId = audio.playID ?: return
108 | soundPool.setVolume(streamId, volume, volume)
109 | }
110 | }
111 |
112 | /**
113 | * 是否初始化
114 | * 如果没有初始化,就使用原来SvgaPlayer库的音频加载逻辑。
115 | * @return true 则已初始化, 否则为 false
116 | */
117 | internal fun isInit(): Boolean {
118 | return soundPool != null
119 | }
120 |
121 | private fun checkInit(): Boolean {
122 | val isInit = isInit()
123 | if (!isInit) {
124 | LogUtils.error(TAG, "soundPool is null, you need call init() !!!")
125 | }
126 | return isInit
127 | }
128 |
129 | private fun getSoundPool(maxStreams: Int) = if (Build.VERSION.SDK_INT >= 21) {
130 | val attributes = AudioAttributes.Builder()
131 | .setUsage(AudioAttributes.USAGE_MEDIA)
132 | .build()
133 | SoundPool.Builder().setAudioAttributes(attributes)
134 | .setMaxStreams(maxStreams)
135 | .build()
136 | } else {
137 | SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0)
138 | }
139 |
140 | internal fun load(callBack: SVGASoundCallBack?,
141 | fd: FileDescriptor?,
142 | offset: Long,
143 | length: Long,
144 | priority: Int): Int {
145 | if (!checkInit()) return -1
146 |
147 | val soundId = soundPool!!.load(fd, offset, length, priority)
148 |
149 | LogUtils.debug(TAG, "load soundId=$soundId callBack=$callBack")
150 |
151 | if (callBack != null && !soundCallBackMap.containsKey(soundId)) {
152 | soundCallBackMap[soundId] = callBack
153 | }
154 | return soundId
155 | }
156 |
157 | internal fun unload(soundId: Int) {
158 | if (!checkInit()) return
159 |
160 | LogUtils.debug(TAG, "unload soundId=$soundId")
161 |
162 | soundPool!!.unload(soundId)
163 |
164 | soundCallBackMap.remove(soundId)
165 | }
166 |
167 | internal fun play(soundId: Int): Int {
168 | if (!checkInit()) return -1
169 |
170 | LogUtils.debug(TAG, "play soundId=$soundId")
171 | return soundPool!!.play(soundId, volume, volume, 1, 0, 1.0f)
172 | }
173 |
174 | internal fun stop(soundId: Int) {
175 | if (!checkInit()) return
176 |
177 | LogUtils.debug(TAG, "stop soundId=$soundId")
178 | soundPool!!.stop(soundId)
179 | }
180 |
181 | internal fun resume(soundId: Int) {
182 | if (!checkInit()) return
183 |
184 | LogUtils.debug(TAG, "stop soundId=$soundId")
185 | soundPool!!.resume(soundId)
186 | }
187 |
188 | internal fun pause(soundId: Int) {
189 | if (!checkInit()) return
190 |
191 | LogUtils.debug(TAG, "pause soundId=$soundId")
192 | soundPool!!.pause(soundId)
193 | }
194 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/Layout.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 27:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Float;
14 | import java.lang.Object;
15 | import java.lang.Override;
16 | import java.lang.String;
17 | import java.lang.StringBuilder;
18 | import okio.ByteString;
19 |
20 | public final class Layout extends Message {
21 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_Layout();
22 |
23 | private static final long serialVersionUID = 0L;
24 |
25 | public static final Float DEFAULT_X = 0.0f;
26 |
27 | public static final Float DEFAULT_Y = 0.0f;
28 |
29 | public static final Float DEFAULT_WIDTH = 0.0f;
30 |
31 | public static final Float DEFAULT_HEIGHT = 0.0f;
32 |
33 | @WireField(
34 | tag = 1,
35 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
36 | )
37 | public final Float x;
38 |
39 | @WireField(
40 | tag = 2,
41 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
42 | )
43 | public final Float y;
44 |
45 | @WireField(
46 | tag = 3,
47 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
48 | )
49 | public final Float width;
50 |
51 | @WireField(
52 | tag = 4,
53 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
54 | )
55 | public final Float height;
56 |
57 | public Layout(Float x, Float y, Float width, Float height) {
58 | this(x, y, width, height, ByteString.EMPTY);
59 | }
60 |
61 | public Layout(Float x, Float y, Float width, Float height, ByteString unknownFields) {
62 | super(ADAPTER, unknownFields);
63 | this.x = x;
64 | this.y = y;
65 | this.width = width;
66 | this.height = height;
67 | }
68 |
69 | @Override
70 | public Builder newBuilder() {
71 | Builder builder = new Builder();
72 | builder.x = x;
73 | builder.y = y;
74 | builder.width = width;
75 | builder.height = height;
76 | builder.addUnknownFields(unknownFields());
77 | return builder;
78 | }
79 |
80 | @Override
81 | public boolean equals(Object other) {
82 | if (other == this) return true;
83 | if (!(other instanceof Layout)) return false;
84 | Layout o = (Layout) other;
85 | return unknownFields().equals(o.unknownFields())
86 | && Internal.equals(x, o.x)
87 | && Internal.equals(y, o.y)
88 | && Internal.equals(width, o.width)
89 | && Internal.equals(height, o.height);
90 | }
91 |
92 | @Override
93 | public int hashCode() {
94 | int result = super.hashCode;
95 | if (result == 0) {
96 | result = unknownFields().hashCode();
97 | result = result * 37 + (x != null ? x.hashCode() : 0);
98 | result = result * 37 + (y != null ? y.hashCode() : 0);
99 | result = result * 37 + (width != null ? width.hashCode() : 0);
100 | result = result * 37 + (height != null ? height.hashCode() : 0);
101 | super.hashCode = result;
102 | }
103 | return result;
104 | }
105 |
106 | @Override
107 | public String toString() {
108 | StringBuilder builder = new StringBuilder();
109 | if (x != null) builder.append(", x=").append(x);
110 | if (y != null) builder.append(", y=").append(y);
111 | if (width != null) builder.append(", width=").append(width);
112 | if (height != null) builder.append(", height=").append(height);
113 | return builder.replace(0, 2, "Layout{").append('}').toString();
114 | }
115 |
116 | public static final class Builder extends Message.Builder {
117 | public Float x;
118 |
119 | public Float y;
120 |
121 | public Float width;
122 |
123 | public Float height;
124 |
125 | public Builder() {
126 | }
127 |
128 | public Builder x(Float x) {
129 | this.x = x;
130 | return this;
131 | }
132 |
133 | public Builder y(Float y) {
134 | this.y = y;
135 | return this;
136 | }
137 |
138 | public Builder width(Float width) {
139 | this.width = width;
140 | return this;
141 | }
142 |
143 | public Builder height(Float height) {
144 | this.height = height;
145 | return this;
146 | }
147 |
148 | @Override
149 | public Layout build() {
150 | return new Layout(x, y, width, height, super.buildUnknownFields());
151 | }
152 | }
153 |
154 | private static final class ProtoAdapter_Layout extends ProtoAdapter {
155 | ProtoAdapter_Layout() {
156 | super(FieldEncoding.LENGTH_DELIMITED, Layout.class);
157 | }
158 |
159 | @Override
160 | public int encodedSize(Layout value) {
161 | return (value.x != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.x) : 0)
162 | + (value.y != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.y) : 0)
163 | + (value.width != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(3, value.width) : 0)
164 | + (value.height != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(4, value.height) : 0)
165 | + value.unknownFields().size();
166 | }
167 |
168 | @Override
169 | public void encode(ProtoWriter writer, Layout value) throws IOException {
170 | if (value.x != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.x);
171 | if (value.y != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.y);
172 | if (value.width != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 3, value.width);
173 | if (value.height != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 4, value.height);
174 | writer.writeBytes(value.unknownFields());
175 | }
176 |
177 | @Override
178 | public Layout decode(ProtoReader reader) throws IOException {
179 | Builder builder = new Builder();
180 | long token = reader.beginMessage();
181 | for (int tag; (tag = reader.nextTag()) != -1;) {
182 | switch (tag) {
183 | case 1: builder.x(ProtoAdapter.FLOAT.decode(reader)); break;
184 | case 2: builder.y(ProtoAdapter.FLOAT.decode(reader)); break;
185 | case 3: builder.width(ProtoAdapter.FLOAT.decode(reader)); break;
186 | case 4: builder.height(ProtoAdapter.FLOAT.decode(reader)); break;
187 | default: {
188 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
189 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
190 | builder.addUnknownField(tag, fieldEncoding, value);
191 | }
192 | }
193 | }
194 | reader.endMessage(token);
195 | return builder.build();
196 | }
197 |
198 | @Override
199 | public Layout redact(Layout value) {
200 | Builder builder = value.newBuilder();
201 | builder.clearUnknownFields();
202 | return builder.build();
203 | }
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/readme.zh.md:
--------------------------------------------------------------------------------
1 | # SVGAPlayer
2 |
3 | ## 介绍
4 |
5 | `SVGAPlayer` 是一个轻量的动画渲染库。你可以使用[工具](http://svga.io/designer.html)从 `Adobe Animate CC` 或者 `Adobe After Effects` 中导出动画文件,然后使用 `SVGAPlayer` 在移动设备上渲染并播放。
6 |
7 | `SVGAPlayer-Android` 使用原生 Android Canvas 库渲染动画,为你提供高性能、低开销的动画体验。
8 |
9 | 如果你想要了解更多细节,请访问[官方网站](http://svga.io/)。
10 |
11 | ## 用法
12 |
13 | 我们在这里介绍 `SVGAPlayer-Android` 的用法。想要知道如何导出动画,点击[这里](http://svga.io/designer.html)。
14 |
15 | ### 使用 Gradle 安装
16 |
17 | 我们的 aar 包托管在 JitPack 上,你需要将 `JitPack.io` 仓库添加到工程 `build.gradle` 中。
18 |
19 | ```
20 | allprojects {
21 | repositories {
22 | ...
23 | maven { url 'https://jitpack.io' }
24 | }
25 | }
26 | ```
27 |
28 | 然后,在应用 `build.gradle` 中添加依赖。
29 |
30 | ```
31 | compile 'com.github.yyued:SVGAPlayer-Android:latest'
32 | ```
33 |
34 | [](https://jitpack.io/#yyued/SVGAPlayer-Android)
35 |
36 | ### Parser 单例支持
37 | SVGAParser 单例需要在使用之前初始化,
38 | 否则会上报错误信息:
39 | `Log.e("SVGAParser", "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")`
40 |
41 |
42 | ### 遮罩支持
43 | 请参阅此处 [Dynamic · Matte Layer](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-%C2%B7-Matte-Layer)
44 |
45 | ### 混淆规则
46 |
47 | ```
48 | -keep class com.squareup.wire.** { *; }
49 | -keep class com.opensource.svgaplayer.proto.** { *; }
50 | ```
51 |
52 | ### 放置 svga 文件
53 |
54 | SVGAPlayer 可以从本地 `assets` 目录,或者远端服务器上加载动画文件。
55 |
56 | ### 使用 XML
57 |
58 | 你可以使用 `layout.xml` 添加一个 `SVGAImageView`。
59 |
60 | ```xml
61 |
62 |
67 |
68 |
74 |
75 |
76 | ```
77 |
78 | 在 XML 中,允许定义以下这些标签:
79 |
80 | #### source: String
81 | 用于表示 svga 文件的路径,提供一个在 `assets` 目录下的文件名,或者提供一个 http url 地址。
82 |
83 | #### autoPlay: Boolean
84 | 默认为 `true`,当动画加载完成后,自动播放。
85 |
86 | #### loopCount: Int
87 | 默认为 `0`,设置动画的循环次数,0 表示无限循环。
88 |
89 | #### ~~clearsAfterStop: Boolean~~
90 | 默认为 `false`,当动画播放完成后,是否清空画布,以及 SVGAVideoEntity 内部数据。
91 | 不再推荐使用,开发者可以通过 clearAfterDetached 控制资源释放,或者手动通过 SVGAVideoEntity#clear 控制资源释放
92 |
93 | #### clearsAfterDetached: Boolean
94 | 默认为 `false`,当 SVGAImageView 触发 onDetachedFromWindow 方法时,是否清空画布。
95 |
96 | #### fillMode: String
97 |
98 | 默认为 `Forward`,可以是 `Forward`、 `Backward`、 `Clear`。
99 |
100 | `Forward` 表示动画结束后,将停留在最后一帧。
101 |
102 | `Backward` 表示动画结束后,将停留在第一帧。
103 |
104 | `Clear` 表示动画播放完后,清空所有画布内容,但仅仅是画布,不涉及 SVGAVideoEntity 内部数据。
105 |
106 | ### 使用代码
107 |
108 | 也可以使用代码添加 `SVGAImageView`。
109 |
110 | #### 创建一个 `SVGAImageView` 实例
111 |
112 | ```kotlin
113 | SVGAImageView imageView = new SVGAImageView(this);
114 | ```
115 |
116 | #### 声明一个 `SVGAParser` 单例.
117 |
118 | ```kotlin
119 | parser = SVGAParser.shareParser()
120 | ```
121 |
122 | #### 初始化 `SVGAParser` 单例
123 |
124 | 必须在使用 `SVGAParser` 单例前初始化,
125 | ```
126 | SVGAParser.shareParser().init(this);
127 | ```
128 |
129 | 否则会上报错误信息:
130 | `Log.e("SVGAParser", "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")`
131 |
132 | 你也可以自行创建 `SVGAParser` 实例。
133 |
134 | #### 创建一个 `SVGAParser` 实例,加载 assets 中的动画。
135 |
136 | ```kotlin
137 | parser = new SVGAParser(this);
138 | // 第三个为可缺省参数,默认为 null,如果设置该方法,则内部不在处理音频的解析以及播放,会通过 PlayCallback 把音频 File 实例回传给开发者,有开发者自行控制音频的播放与停止。
139 | parser.decodeFromAssets("posche.svga", object : SVGAParser.ParseCompletion {
140 | // ...
141 | }, object : SVGAParser.PlayCallback {
142 | // The default is null, can not be set
143 | })
144 | ```
145 |
146 | #### 创建一个 `SVGAParser` 实例,加载远端服务器中的动画。
147 |
148 | ```kotlin
149 | parser = new SVGAParser(this);
150 | // 第三个为可缺省参数,默认为 null,如果设置该方法,则内部不在处理音频的解析以及播放,会通过 PlayCallback 把音频 File 实例回传给开发者,有开发者自行控制音频的播放与停止。
151 | parser.decodeFromURL(new URL("https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true"), new SVGAParser.ParseCompletion() {
152 | // ...
153 | }, object : SVGAParser.PlayCallback {
154 | // The default is null, can not be set
155 | })
156 | ```
157 |
158 | #### 创建一个 `SVGADrawable` 实例,并赋值给 `SVGAImageView`,然后播放动画。
159 |
160 | ```kotlin
161 | parser = new SVGAParser(this);
162 | parser.decodeFromURL(..., new SVGAParser.ParseCompletion() {
163 | @Override
164 | public void onComplete(@NotNull SVGAVideoEntity videoItem) {
165 | SVGADrawable drawable = new SVGADrawable(videoItem);
166 | imageView.setImageDrawable(drawable);
167 | imageView.startAnimation();
168 | }
169 | @Override
170 | public void onError() {
171 |
172 | }
173 | });
174 | ```
175 |
176 | ### 缓存
177 |
178 | `SVGAParser` 不会管理缓存,你需要自行实现缓存器。
179 |
180 | #### 设置 HttpResponseCache
181 |
182 | `SVGAParser` 依赖 `URLConnection`, `URLConnection` 使用 `HttpResponseCache` 处理缓存。
183 |
184 | 添加代码至 `Application.java:onCreate` 以设置缓存。
185 |
186 | ```kotlin
187 | val cacheDir = File(context.applicationContext.cacheDir, "http")
188 | HttpResponseCache.install(cacheDir, 1024 * 1024 * 128)
189 | ```
190 |
191 | ### SVGALogger
192 | 更新了内部 log 输出,可通过 SVGALogger 去管理和控制,默认是未启用 log 输出,开发者们也可以实现 ILogger 接口,做到外部捕获收集 log,方便排查问题。
193 | 通过 `setLogEnabled` 方法设置日志是否开启。
194 | 通过 `injectSVGALoggerImp` 方法注入自定义 ILogger 实现类。
195 |
196 | ```kotlin
197 |
198 | // 默认情况下,SVGA 内部不会输出任何 log,所以需要手动设置为 true
199 | SVGALogger.setLogEnabled(true)
200 |
201 | // 如果希望收集 SVGA 内部输出的日志,则可通过下面方式获取
202 | SVGALogger.injectSVGALoggerImp(object: ILogger {
203 | // 实现相关接口进行接收 log
204 | })
205 | ```
206 |
207 | ### SVGASoundManager
208 | 新增 SVGASoundManager 控制 SVGA 音频,需要手动调用 init 方法进行初始化,否则按照默认的音频加载逻辑。
209 | 另外通过 SVGASoundManager#setVolume 可控制 SVGA 播放时的音量大小,范围值在 [0f, 1f],默认控制所有 SVGA 播放时的音量,
210 | 而且该方法可设置第二个可缺省参数:SVGAVideoEntity,表示仅控制当前 SVGA 的音量大小,其他 SVGA 的音量保持不变。
211 |
212 | ```kotlin
213 | // 初始化音频管理器,方便管理音频播放
214 | // 如果没有初始化,则默认按照原有方式加载音频
215 | SVGASoundManager.init()
216 |
217 | // 释放音频资源
218 | SVGASoundManager.release()
219 |
220 | /**
221 | * 设置音量大小,entity 默认为空
222 | * 当 entity 为空,则控制所有通过 SVGASoundManager 加载的音频音量大小,即包括当前正在播放的音频以及后续加载的音频
223 | * 当 entity 不为空,则仅控制该实例的 SVGA 音频音量大小,其他则不受影响
224 | *
225 | * @param volume 取值范围为 [0f, 1f]
226 | * @param entity 即 SVGAParser 回调回来的实例
227 | */
228 | SVGASoundManager.setVolume(volume, entity)
229 | ```
230 |
231 |
232 | ## 功能示例
233 |
234 | * [使用位图替换指定元素。](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-Image)
235 | * [在指定元素上绘制文本。](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-Text)
236 | * [在指定元素上绘制富文本。](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-Text-Layout)
237 | * [隐藏指定元素。](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-Hidden)
238 | * [在指定元素上自由绘制。](https://github.com/yyued/SVGAPlayer-Android/wiki/Dynamic-Drawer)
239 |
240 | ## APIs
241 |
242 | 请参阅此处 [https://github.com/yyued/SVGAPlayer-Android/wiki/APIs](https://github.com/yyued/SVGAPlayer-Android/wiki/APIs)
243 |
244 | ## CHANGELOG
245 |
246 | 请参阅此处 [CHANGELOG](./CHANGELOG.md)
247 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/SpriteEntity.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 13:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Object;
14 | import java.lang.Override;
15 | import java.lang.String;
16 | import java.lang.StringBuilder;
17 | import java.util.List;
18 | import okio.ByteString;
19 |
20 | public final class SpriteEntity extends Message {
21 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_SpriteEntity();
22 |
23 | private static final long serialVersionUID = 0L;
24 |
25 | public static final String DEFAULT_IMAGEKEY = "";
26 |
27 | public static final String DEFAULT_MATTEKEY = "";
28 |
29 | /**
30 | * 元件所对应的位图键名, 如果 imageKey 含有 .vector 后缀,该 sprite 为矢量图层 含有 .matte 后缀,该 sprite 为遮罩图层。
31 | */
32 | @WireField(
33 | tag = 1,
34 | adapter = "com.squareup.wire.ProtoAdapter#STRING"
35 | )
36 | public final String imageKey;
37 |
38 | /**
39 | * 帧列表
40 | */
41 | @WireField(
42 | tag = 2,
43 | adapter = "com.opensource.svgaplayer.proto.FrameEntity#ADAPTER",
44 | label = WireField.Label.REPEATED
45 | )
46 | public final List frames;
47 |
48 | /**
49 | * 被遮罩图层的 matteKey 对应的是其遮罩图层的 imageKey.
50 | */
51 | @WireField(
52 | tag = 3,
53 | adapter = "com.squareup.wire.ProtoAdapter#STRING"
54 | )
55 | public final String matteKey;
56 |
57 | public SpriteEntity(String imageKey, List frames, String matteKey) {
58 | this(imageKey, frames, matteKey, ByteString.EMPTY);
59 | }
60 |
61 | public SpriteEntity(String imageKey, List frames, String matteKey, ByteString unknownFields) {
62 | super(ADAPTER, unknownFields);
63 | this.imageKey = imageKey;
64 | this.frames = Internal.immutableCopyOf("frames", frames);
65 | this.matteKey = matteKey;
66 | }
67 |
68 | @Override
69 | public Builder newBuilder() {
70 | Builder builder = new Builder();
71 | builder.imageKey = imageKey;
72 | builder.frames = Internal.copyOf("frames", frames);
73 | builder.matteKey = matteKey;
74 | builder.addUnknownFields(unknownFields());
75 | return builder;
76 | }
77 |
78 | @Override
79 | public boolean equals(Object other) {
80 | if (other == this) return true;
81 | if (!(other instanceof SpriteEntity)) return false;
82 | SpriteEntity o = (SpriteEntity) other;
83 | return unknownFields().equals(o.unknownFields())
84 | && Internal.equals(imageKey, o.imageKey)
85 | && frames.equals(o.frames)
86 | && Internal.equals(matteKey, o.matteKey);
87 | }
88 |
89 | @Override
90 | public int hashCode() {
91 | int result = super.hashCode;
92 | if (result == 0) {
93 | result = unknownFields().hashCode();
94 | result = result * 37 + (imageKey != null ? imageKey.hashCode() : 0);
95 | result = result * 37 + frames.hashCode();
96 | result = result * 37 + (matteKey != null ? matteKey.hashCode() : 0);
97 | super.hashCode = result;
98 | }
99 | return result;
100 | }
101 |
102 | @Override
103 | public String toString() {
104 | StringBuilder builder = new StringBuilder();
105 | if (imageKey != null) builder.append(", imageKey=").append(imageKey);
106 | if (!frames.isEmpty()) builder.append(", frames=").append(frames);
107 | if (matteKey != null) builder.append(", matteKey=").append(matteKey);
108 | return builder.replace(0, 2, "SpriteEntity{").append('}').toString();
109 | }
110 |
111 | public static final class Builder extends Message.Builder {
112 | public String imageKey;
113 |
114 | public List frames;
115 |
116 | public String matteKey;
117 |
118 | public Builder() {
119 | frames = Internal.newMutableList();
120 | }
121 |
122 | /**
123 | * 元件所对应的位图键名, 如果 imageKey 含有 .vector 后缀,该 sprite 为矢量图层 含有 .matte 后缀,该 sprite 为遮罩图层。
124 | */
125 | public Builder imageKey(String imageKey) {
126 | this.imageKey = imageKey;
127 | return this;
128 | }
129 |
130 | /**
131 | * 帧列表
132 | */
133 | public Builder frames(List frames) {
134 | Internal.checkElementsNotNull(frames);
135 | this.frames = frames;
136 | return this;
137 | }
138 |
139 | /**
140 | * 被遮罩图层的 matteKey 对应的是其遮罩图层的 imageKey.
141 | */
142 | public Builder matteKey(String matteKey) {
143 | this.matteKey = matteKey;
144 | return this;
145 | }
146 |
147 | @Override
148 | public SpriteEntity build() {
149 | return new SpriteEntity(imageKey, frames, matteKey, super.buildUnknownFields());
150 | }
151 | }
152 |
153 | private static final class ProtoAdapter_SpriteEntity extends ProtoAdapter {
154 | ProtoAdapter_SpriteEntity() {
155 | super(FieldEncoding.LENGTH_DELIMITED, SpriteEntity.class);
156 | }
157 |
158 | @Override
159 | public int encodedSize(SpriteEntity value) {
160 | return (value.imageKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.imageKey) : 0)
161 | + FrameEntity.ADAPTER.asRepeated().encodedSizeWithTag(2, value.frames)
162 | + (value.matteKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(3, value.matteKey) : 0)
163 | + value.unknownFields().size();
164 | }
165 |
166 | @Override
167 | public void encode(ProtoWriter writer, SpriteEntity value) throws IOException {
168 | if (value.imageKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.imageKey);
169 | FrameEntity.ADAPTER.asRepeated().encodeWithTag(writer, 2, value.frames);
170 | if (value.matteKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 3, value.matteKey);
171 | writer.writeBytes(value.unknownFields());
172 | }
173 |
174 | @Override
175 | public SpriteEntity decode(ProtoReader reader) throws IOException {
176 | Builder builder = new Builder();
177 | long token = reader.beginMessage();
178 | for (int tag; (tag = reader.nextTag()) != -1;) {
179 | switch (tag) {
180 | case 1: builder.imageKey(ProtoAdapter.STRING.decode(reader)); break;
181 | case 2: builder.frames.add(FrameEntity.ADAPTER.decode(reader)); break;
182 | case 3: builder.matteKey(ProtoAdapter.STRING.decode(reader)); break;
183 | default: {
184 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
185 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
186 | builder.addUnknownField(tag, fieldEncoding, value);
187 | }
188 | }
189 | }
190 | reader.endMessage(token);
191 | return builder.build();
192 | }
193 |
194 | @Override
195 | public SpriteEntity redact(SpriteEntity value) {
196 | Builder builder = value.newBuilder();
197 | Internal.redactElements(builder.frames, FrameEntity.ADAPTER);
198 | builder.clearUnknownFields();
199 | return builder.build();
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/MovieParams.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 6:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Float;
14 | import java.lang.Integer;
15 | import java.lang.Object;
16 | import java.lang.Override;
17 | import java.lang.String;
18 | import java.lang.StringBuilder;
19 | import okio.ByteString;
20 |
21 | public final class MovieParams extends Message {
22 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_MovieParams();
23 |
24 | private static final long serialVersionUID = 0L;
25 |
26 | public static final Float DEFAULT_VIEWBOXWIDTH = 0.0f;
27 |
28 | public static final Float DEFAULT_VIEWBOXHEIGHT = 0.0f;
29 |
30 | public static final Integer DEFAULT_FPS = 0;
31 |
32 | public static final Integer DEFAULT_FRAMES = 0;
33 |
34 | /**
35 | * 画布宽
36 | */
37 | @WireField(
38 | tag = 1,
39 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
40 | )
41 | public final Float viewBoxWidth;
42 |
43 | /**
44 | * 画布高
45 | */
46 | @WireField(
47 | tag = 2,
48 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
49 | )
50 | public final Float viewBoxHeight;
51 |
52 | /**
53 | * 动画每秒播放帧数,合法值是 [1, 2, 3, 5, 6, 10, 12, 15, 20, 30, 60] 中的任意一个。
54 | */
55 | @WireField(
56 | tag = 3,
57 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
58 | )
59 | public final Integer fps;
60 |
61 | /**
62 | * 动画总帧数
63 | */
64 | @WireField(
65 | tag = 4,
66 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
67 | )
68 | public final Integer frames;
69 |
70 | public MovieParams(Float viewBoxWidth, Float viewBoxHeight, Integer fps, Integer frames) {
71 | this(viewBoxWidth, viewBoxHeight, fps, frames, ByteString.EMPTY);
72 | }
73 |
74 | public MovieParams(Float viewBoxWidth, Float viewBoxHeight, Integer fps, Integer frames, ByteString unknownFields) {
75 | super(ADAPTER, unknownFields);
76 | this.viewBoxWidth = viewBoxWidth;
77 | this.viewBoxHeight = viewBoxHeight;
78 | this.fps = fps;
79 | this.frames = frames;
80 | }
81 |
82 | @Override
83 | public Builder newBuilder() {
84 | Builder builder = new Builder();
85 | builder.viewBoxWidth = viewBoxWidth;
86 | builder.viewBoxHeight = viewBoxHeight;
87 | builder.fps = fps;
88 | builder.frames = frames;
89 | builder.addUnknownFields(unknownFields());
90 | return builder;
91 | }
92 |
93 | @Override
94 | public boolean equals(Object other) {
95 | if (other == this) return true;
96 | if (!(other instanceof MovieParams)) return false;
97 | MovieParams o = (MovieParams) other;
98 | return unknownFields().equals(o.unknownFields())
99 | && Internal.equals(viewBoxWidth, o.viewBoxWidth)
100 | && Internal.equals(viewBoxHeight, o.viewBoxHeight)
101 | && Internal.equals(fps, o.fps)
102 | && Internal.equals(frames, o.frames);
103 | }
104 |
105 | @Override
106 | public int hashCode() {
107 | int result = super.hashCode;
108 | if (result == 0) {
109 | result = unknownFields().hashCode();
110 | result = result * 37 + (viewBoxWidth != null ? viewBoxWidth.hashCode() : 0);
111 | result = result * 37 + (viewBoxHeight != null ? viewBoxHeight.hashCode() : 0);
112 | result = result * 37 + (fps != null ? fps.hashCode() : 0);
113 | result = result * 37 + (frames != null ? frames.hashCode() : 0);
114 | super.hashCode = result;
115 | }
116 | return result;
117 | }
118 |
119 | @Override
120 | public String toString() {
121 | StringBuilder builder = new StringBuilder();
122 | if (viewBoxWidth != null) builder.append(", viewBoxWidth=").append(viewBoxWidth);
123 | if (viewBoxHeight != null) builder.append(", viewBoxHeight=").append(viewBoxHeight);
124 | if (fps != null) builder.append(", fps=").append(fps);
125 | if (frames != null) builder.append(", frames=").append(frames);
126 | return builder.replace(0, 2, "MovieParams{").append('}').toString();
127 | }
128 |
129 | public static final class Builder extends Message.Builder {
130 | public Float viewBoxWidth;
131 |
132 | public Float viewBoxHeight;
133 |
134 | public Integer fps;
135 |
136 | public Integer frames;
137 |
138 | public Builder() {
139 | }
140 |
141 | /**
142 | * 画布宽
143 | */
144 | public Builder viewBoxWidth(Float viewBoxWidth) {
145 | this.viewBoxWidth = viewBoxWidth;
146 | return this;
147 | }
148 |
149 | /**
150 | * 画布高
151 | */
152 | public Builder viewBoxHeight(Float viewBoxHeight) {
153 | this.viewBoxHeight = viewBoxHeight;
154 | return this;
155 | }
156 |
157 | /**
158 | * 动画每秒播放帧数,合法值是 [1, 2, 3, 5, 6, 10, 12, 15, 20, 30, 60] 中的任意一个。
159 | */
160 | public Builder fps(Integer fps) {
161 | this.fps = fps;
162 | return this;
163 | }
164 |
165 | /**
166 | * 动画总帧数
167 | */
168 | public Builder frames(Integer frames) {
169 | this.frames = frames;
170 | return this;
171 | }
172 |
173 | @Override
174 | public MovieParams build() {
175 | return new MovieParams(viewBoxWidth, viewBoxHeight, fps, frames, super.buildUnknownFields());
176 | }
177 | }
178 |
179 | private static final class ProtoAdapter_MovieParams extends ProtoAdapter {
180 | ProtoAdapter_MovieParams() {
181 | super(FieldEncoding.LENGTH_DELIMITED, MovieParams.class);
182 | }
183 |
184 | @Override
185 | public int encodedSize(MovieParams value) {
186 | return (value.viewBoxWidth != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.viewBoxWidth) : 0)
187 | + (value.viewBoxHeight != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.viewBoxHeight) : 0)
188 | + (value.fps != null ? ProtoAdapter.INT32.encodedSizeWithTag(3, value.fps) : 0)
189 | + (value.frames != null ? ProtoAdapter.INT32.encodedSizeWithTag(4, value.frames) : 0)
190 | + value.unknownFields().size();
191 | }
192 |
193 | @Override
194 | public void encode(ProtoWriter writer, MovieParams value) throws IOException {
195 | if (value.viewBoxWidth != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.viewBoxWidth);
196 | if (value.viewBoxHeight != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.viewBoxHeight);
197 | if (value.fps != null) ProtoAdapter.INT32.encodeWithTag(writer, 3, value.fps);
198 | if (value.frames != null) ProtoAdapter.INT32.encodeWithTag(writer, 4, value.frames);
199 | writer.writeBytes(value.unknownFields());
200 | }
201 |
202 | @Override
203 | public MovieParams decode(ProtoReader reader) throws IOException {
204 | Builder builder = new Builder();
205 | long token = reader.beginMessage();
206 | for (int tag; (tag = reader.nextTag()) != -1;) {
207 | switch (tag) {
208 | case 1: builder.viewBoxWidth(ProtoAdapter.FLOAT.decode(reader)); break;
209 | case 2: builder.viewBoxHeight(ProtoAdapter.FLOAT.decode(reader)); break;
210 | case 3: builder.fps(ProtoAdapter.INT32.decode(reader)); break;
211 | case 4: builder.frames(ProtoAdapter.INT32.decode(reader)); break;
212 | default: {
213 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
214 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
215 | builder.addUnknownField(tag, fieldEncoding, value);
216 | }
217 | }
218 | }
219 | reader.endMessage(token);
220 | return builder.build();
221 | }
222 |
223 | @Override
224 | public MovieParams redact(MovieParams value) {
225 | Builder builder = value.newBuilder();
226 | builder.clearUnknownFields();
227 | return builder.build();
228 | }
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/Transform.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 34:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Float;
14 | import java.lang.Object;
15 | import java.lang.Override;
16 | import java.lang.String;
17 | import java.lang.StringBuilder;
18 | import okio.ByteString;
19 |
20 | public final class Transform extends Message {
21 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_Transform();
22 |
23 | private static final long serialVersionUID = 0L;
24 |
25 | public static final Float DEFAULT_A = 0.0f;
26 |
27 | public static final Float DEFAULT_B = 0.0f;
28 |
29 | public static final Float DEFAULT_C = 0.0f;
30 |
31 | public static final Float DEFAULT_D = 0.0f;
32 |
33 | public static final Float DEFAULT_TX = 0.0f;
34 |
35 | public static final Float DEFAULT_TY = 0.0f;
36 |
37 | @WireField(
38 | tag = 1,
39 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
40 | )
41 | public final Float a;
42 |
43 | @WireField(
44 | tag = 2,
45 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
46 | )
47 | public final Float b;
48 |
49 | @WireField(
50 | tag = 3,
51 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
52 | )
53 | public final Float c;
54 |
55 | @WireField(
56 | tag = 4,
57 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
58 | )
59 | public final Float d;
60 |
61 | @WireField(
62 | tag = 5,
63 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
64 | )
65 | public final Float tx;
66 |
67 | @WireField(
68 | tag = 6,
69 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
70 | )
71 | public final Float ty;
72 |
73 | public Transform(Float a, Float b, Float c, Float d, Float tx, Float ty) {
74 | this(a, b, c, d, tx, ty, ByteString.EMPTY);
75 | }
76 |
77 | public Transform(Float a, Float b, Float c, Float d, Float tx, Float ty, ByteString unknownFields) {
78 | super(ADAPTER, unknownFields);
79 | this.a = a;
80 | this.b = b;
81 | this.c = c;
82 | this.d = d;
83 | this.tx = tx;
84 | this.ty = ty;
85 | }
86 |
87 | @Override
88 | public Builder newBuilder() {
89 | Builder builder = new Builder();
90 | builder.a = a;
91 | builder.b = b;
92 | builder.c = c;
93 | builder.d = d;
94 | builder.tx = tx;
95 | builder.ty = ty;
96 | builder.addUnknownFields(unknownFields());
97 | return builder;
98 | }
99 |
100 | @Override
101 | public boolean equals(Object other) {
102 | if (other == this) return true;
103 | if (!(other instanceof Transform)) return false;
104 | Transform o = (Transform) other;
105 | return unknownFields().equals(o.unknownFields())
106 | && Internal.equals(a, o.a)
107 | && Internal.equals(b, o.b)
108 | && Internal.equals(c, o.c)
109 | && Internal.equals(d, o.d)
110 | && Internal.equals(tx, o.tx)
111 | && Internal.equals(ty, o.ty);
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | int result = super.hashCode;
117 | if (result == 0) {
118 | result = unknownFields().hashCode();
119 | result = result * 37 + (a != null ? a.hashCode() : 0);
120 | result = result * 37 + (b != null ? b.hashCode() : 0);
121 | result = result * 37 + (c != null ? c.hashCode() : 0);
122 | result = result * 37 + (d != null ? d.hashCode() : 0);
123 | result = result * 37 + (tx != null ? tx.hashCode() : 0);
124 | result = result * 37 + (ty != null ? ty.hashCode() : 0);
125 | super.hashCode = result;
126 | }
127 | return result;
128 | }
129 |
130 | @Override
131 | public String toString() {
132 | StringBuilder builder = new StringBuilder();
133 | if (a != null) builder.append(", a=").append(a);
134 | if (b != null) builder.append(", b=").append(b);
135 | if (c != null) builder.append(", c=").append(c);
136 | if (d != null) builder.append(", d=").append(d);
137 | if (tx != null) builder.append(", tx=").append(tx);
138 | if (ty != null) builder.append(", ty=").append(ty);
139 | return builder.replace(0, 2, "Transform{").append('}').toString();
140 | }
141 |
142 | public static final class Builder extends Message.Builder {
143 | public Float a;
144 |
145 | public Float b;
146 |
147 | public Float c;
148 |
149 | public Float d;
150 |
151 | public Float tx;
152 |
153 | public Float ty;
154 |
155 | public Builder() {
156 | }
157 |
158 | public Builder a(Float a) {
159 | this.a = a;
160 | return this;
161 | }
162 |
163 | public Builder b(Float b) {
164 | this.b = b;
165 | return this;
166 | }
167 |
168 | public Builder c(Float c) {
169 | this.c = c;
170 | return this;
171 | }
172 |
173 | public Builder d(Float d) {
174 | this.d = d;
175 | return this;
176 | }
177 |
178 | public Builder tx(Float tx) {
179 | this.tx = tx;
180 | return this;
181 | }
182 |
183 | public Builder ty(Float ty) {
184 | this.ty = ty;
185 | return this;
186 | }
187 |
188 | @Override
189 | public Transform build() {
190 | return new Transform(a, b, c, d, tx, ty, super.buildUnknownFields());
191 | }
192 | }
193 |
194 | private static final class ProtoAdapter_Transform extends ProtoAdapter {
195 | ProtoAdapter_Transform() {
196 | super(FieldEncoding.LENGTH_DELIMITED, Transform.class);
197 | }
198 |
199 | @Override
200 | public int encodedSize(Transform value) {
201 | return (value.a != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.a) : 0)
202 | + (value.b != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.b) : 0)
203 | + (value.c != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(3, value.c) : 0)
204 | + (value.d != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(4, value.d) : 0)
205 | + (value.tx != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(5, value.tx) : 0)
206 | + (value.ty != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(6, value.ty) : 0)
207 | + value.unknownFields().size();
208 | }
209 |
210 | @Override
211 | public void encode(ProtoWriter writer, Transform value) throws IOException {
212 | if (value.a != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.a);
213 | if (value.b != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.b);
214 | if (value.c != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 3, value.c);
215 | if (value.d != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 4, value.d);
216 | if (value.tx != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 5, value.tx);
217 | if (value.ty != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 6, value.ty);
218 | writer.writeBytes(value.unknownFields());
219 | }
220 |
221 | @Override
222 | public Transform decode(ProtoReader reader) throws IOException {
223 | Builder builder = new Builder();
224 | long token = reader.beginMessage();
225 | for (int tag; (tag = reader.nextTag()) != -1;) {
226 | switch (tag) {
227 | case 1: builder.a(ProtoAdapter.FLOAT.decode(reader)); break;
228 | case 2: builder.b(ProtoAdapter.FLOAT.decode(reader)); break;
229 | case 3: builder.c(ProtoAdapter.FLOAT.decode(reader)); break;
230 | case 4: builder.d(ProtoAdapter.FLOAT.decode(reader)); break;
231 | case 5: builder.tx(ProtoAdapter.FLOAT.decode(reader)); break;
232 | case 6: builder.ty(ProtoAdapter.FLOAT.decode(reader)); break;
233 | default: {
234 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
235 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
236 | builder.addUnknownField(tag, fieldEncoding, value);
237 | }
238 | }
239 | }
240 | reader.endMessage(token);
241 | return builder.build();
242 | }
243 |
244 | @Override
245 | public Transform redact(Transform value) {
246 | Builder builder = value.newBuilder();
247 | builder.clearUnknownFields();
248 | return builder.build();
249 | }
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/AudioEntity.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 19:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Integer;
14 | import java.lang.Object;
15 | import java.lang.Override;
16 | import java.lang.String;
17 | import java.lang.StringBuilder;
18 | import okio.ByteString;
19 |
20 | public final class AudioEntity extends Message {
21 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_AudioEntity();
22 |
23 | private static final long serialVersionUID = 0L;
24 |
25 | public static final String DEFAULT_AUDIOKEY = "";
26 |
27 | public static final Integer DEFAULT_STARTFRAME = 0;
28 |
29 | public static final Integer DEFAULT_ENDFRAME = 0;
30 |
31 | public static final Integer DEFAULT_STARTTIME = 0;
32 |
33 | public static final Integer DEFAULT_TOTALTIME = 0;
34 |
35 | /**
36 | * 音频文件名
37 | */
38 | @WireField(
39 | tag = 1,
40 | adapter = "com.squareup.wire.ProtoAdapter#STRING"
41 | )
42 | public final String audioKey;
43 |
44 | /**
45 | * 音频播放起始帧
46 | */
47 | @WireField(
48 | tag = 2,
49 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
50 | )
51 | public final Integer startFrame;
52 |
53 | /**
54 | * 音频播放结束帧
55 | */
56 | @WireField(
57 | tag = 3,
58 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
59 | )
60 | public final Integer endFrame;
61 |
62 | /**
63 | * 音频播放起始时间(相对音频长度)
64 | */
65 | @WireField(
66 | tag = 4,
67 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
68 | )
69 | public final Integer startTime;
70 |
71 | /**
72 | * 音频总长度
73 | */
74 | @WireField(
75 | tag = 5,
76 | adapter = "com.squareup.wire.ProtoAdapter#INT32"
77 | )
78 | public final Integer totalTime;
79 |
80 | public AudioEntity(String audioKey, Integer startFrame, Integer endFrame, Integer startTime, Integer totalTime) {
81 | this(audioKey, startFrame, endFrame, startTime, totalTime, ByteString.EMPTY);
82 | }
83 |
84 | public AudioEntity(String audioKey, Integer startFrame, Integer endFrame, Integer startTime, Integer totalTime, ByteString unknownFields) {
85 | super(ADAPTER, unknownFields);
86 | this.audioKey = audioKey;
87 | this.startFrame = startFrame;
88 | this.endFrame = endFrame;
89 | this.startTime = startTime;
90 | this.totalTime = totalTime;
91 | }
92 |
93 | @Override
94 | public Builder newBuilder() {
95 | Builder builder = new Builder();
96 | builder.audioKey = audioKey;
97 | builder.startFrame = startFrame;
98 | builder.endFrame = endFrame;
99 | builder.startTime = startTime;
100 | builder.totalTime = totalTime;
101 | builder.addUnknownFields(unknownFields());
102 | return builder;
103 | }
104 |
105 | @Override
106 | public boolean equals(Object other) {
107 | if (other == this) return true;
108 | if (!(other instanceof AudioEntity)) return false;
109 | AudioEntity o = (AudioEntity) other;
110 | return unknownFields().equals(o.unknownFields())
111 | && Internal.equals(audioKey, o.audioKey)
112 | && Internal.equals(startFrame, o.startFrame)
113 | && Internal.equals(endFrame, o.endFrame)
114 | && Internal.equals(startTime, o.startTime)
115 | && Internal.equals(totalTime, o.totalTime);
116 | }
117 |
118 | @Override
119 | public int hashCode() {
120 | int result = super.hashCode;
121 | if (result == 0) {
122 | result = unknownFields().hashCode();
123 | result = result * 37 + (audioKey != null ? audioKey.hashCode() : 0);
124 | result = result * 37 + (startFrame != null ? startFrame.hashCode() : 0);
125 | result = result * 37 + (endFrame != null ? endFrame.hashCode() : 0);
126 | result = result * 37 + (startTime != null ? startTime.hashCode() : 0);
127 | result = result * 37 + (totalTime != null ? totalTime.hashCode() : 0);
128 | super.hashCode = result;
129 | }
130 | return result;
131 | }
132 |
133 | @Override
134 | public String toString() {
135 | StringBuilder builder = new StringBuilder();
136 | if (audioKey != null) builder.append(", audioKey=").append(audioKey);
137 | if (startFrame != null) builder.append(", startFrame=").append(startFrame);
138 | if (endFrame != null) builder.append(", endFrame=").append(endFrame);
139 | if (startTime != null) builder.append(", startTime=").append(startTime);
140 | if (totalTime != null) builder.append(", totalTime=").append(totalTime);
141 | return builder.replace(0, 2, "AudioEntity{").append('}').toString();
142 | }
143 |
144 | public static final class Builder extends Message.Builder {
145 | public String audioKey;
146 |
147 | public Integer startFrame;
148 |
149 | public Integer endFrame;
150 |
151 | public Integer startTime;
152 |
153 | public Integer totalTime;
154 |
155 | public Builder() {
156 | }
157 |
158 | /**
159 | * 音频文件名
160 | */
161 | public Builder audioKey(String audioKey) {
162 | this.audioKey = audioKey;
163 | return this;
164 | }
165 |
166 | /**
167 | * 音频播放起始帧
168 | */
169 | public Builder startFrame(Integer startFrame) {
170 | this.startFrame = startFrame;
171 | return this;
172 | }
173 |
174 | /**
175 | * 音频播放结束帧
176 | */
177 | public Builder endFrame(Integer endFrame) {
178 | this.endFrame = endFrame;
179 | return this;
180 | }
181 |
182 | /**
183 | * 音频播放起始时间(相对音频长度)
184 | */
185 | public Builder startTime(Integer startTime) {
186 | this.startTime = startTime;
187 | return this;
188 | }
189 |
190 | /**
191 | * 音频总长度
192 | */
193 | public Builder totalTime(Integer totalTime) {
194 | this.totalTime = totalTime;
195 | return this;
196 | }
197 |
198 | @Override
199 | public AudioEntity build() {
200 | return new AudioEntity(audioKey, startFrame, endFrame, startTime, totalTime, super.buildUnknownFields());
201 | }
202 | }
203 |
204 | private static final class ProtoAdapter_AudioEntity extends ProtoAdapter {
205 | ProtoAdapter_AudioEntity() {
206 | super(FieldEncoding.LENGTH_DELIMITED, AudioEntity.class);
207 | }
208 |
209 | @Override
210 | public int encodedSize(AudioEntity value) {
211 | return (value.audioKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.audioKey) : 0)
212 | + (value.startFrame != null ? ProtoAdapter.INT32.encodedSizeWithTag(2, value.startFrame) : 0)
213 | + (value.endFrame != null ? ProtoAdapter.INT32.encodedSizeWithTag(3, value.endFrame) : 0)
214 | + (value.startTime != null ? ProtoAdapter.INT32.encodedSizeWithTag(4, value.startTime) : 0)
215 | + (value.totalTime != null ? ProtoAdapter.INT32.encodedSizeWithTag(5, value.totalTime) : 0)
216 | + value.unknownFields().size();
217 | }
218 |
219 | @Override
220 | public void encode(ProtoWriter writer, AudioEntity value) throws IOException {
221 | if (value.audioKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.audioKey);
222 | if (value.startFrame != null) ProtoAdapter.INT32.encodeWithTag(writer, 2, value.startFrame);
223 | if (value.endFrame != null) ProtoAdapter.INT32.encodeWithTag(writer, 3, value.endFrame);
224 | if (value.startTime != null) ProtoAdapter.INT32.encodeWithTag(writer, 4, value.startTime);
225 | if (value.totalTime != null) ProtoAdapter.INT32.encodeWithTag(writer, 5, value.totalTime);
226 | writer.writeBytes(value.unknownFields());
227 | }
228 |
229 | @Override
230 | public AudioEntity decode(ProtoReader reader) throws IOException {
231 | Builder builder = new Builder();
232 | long token = reader.beginMessage();
233 | for (int tag; (tag = reader.nextTag()) != -1;) {
234 | switch (tag) {
235 | case 1: builder.audioKey(ProtoAdapter.STRING.decode(reader)); break;
236 | case 2: builder.startFrame(ProtoAdapter.INT32.decode(reader)); break;
237 | case 3: builder.endFrame(ProtoAdapter.INT32.decode(reader)); break;
238 | case 4: builder.startTime(ProtoAdapter.INT32.decode(reader)); break;
239 | case 5: builder.totalTime(ProtoAdapter.INT32.decode(reader)); break;
240 | default: {
241 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
242 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
243 | builder.addUnknownField(tag, fieldEncoding, value);
244 | }
245 | }
246 | }
247 | reader.endMessage(token);
248 | return builder.build();
249 | }
250 |
251 | @Override
252 | public AudioEntity redact(AudioEntity value) {
253 | Builder builder = value.newBuilder();
254 | builder.clearUnknownFields();
255 | return builder.build();
256 | }
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/FrameEntity.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 115:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Float;
14 | import java.lang.Object;
15 | import java.lang.Override;
16 | import java.lang.String;
17 | import java.lang.StringBuilder;
18 | import java.util.List;
19 | import okio.ByteString;
20 |
21 | public final class FrameEntity extends Message {
22 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_FrameEntity();
23 |
24 | private static final long serialVersionUID = 0L;
25 |
26 | public static final Float DEFAULT_ALPHA = 0.0f;
27 |
28 | public static final String DEFAULT_CLIPPATH = "";
29 |
30 | /**
31 | * 透明度
32 | */
33 | @WireField(
34 | tag = 1,
35 | adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
36 | )
37 | public final Float alpha;
38 |
39 | /**
40 | * 初始约束大小
41 | */
42 | @WireField(
43 | tag = 2,
44 | adapter = "com.opensource.svgaplayer.proto.Layout#ADAPTER"
45 | )
46 | public final Layout layout;
47 |
48 | /**
49 | * 2D 变换矩阵
50 | */
51 | @WireField(
52 | tag = 3,
53 | adapter = "com.opensource.svgaplayer.proto.Transform#ADAPTER"
54 | )
55 | public final Transform transform;
56 |
57 | /**
58 | * 遮罩路径,使用 SVG 标准 Path 绘制图案进行 Mask 遮罩。
59 | */
60 | @WireField(
61 | tag = 4,
62 | adapter = "com.squareup.wire.ProtoAdapter#STRING"
63 | )
64 | public final String clipPath;
65 |
66 | /**
67 | * 矢量元素列表
68 | */
69 | @WireField(
70 | tag = 5,
71 | adapter = "com.opensource.svgaplayer.proto.ShapeEntity#ADAPTER",
72 | label = WireField.Label.REPEATED
73 | )
74 | public final List shapes;
75 |
76 | public FrameEntity(Float alpha, Layout layout, Transform transform, String clipPath, List shapes) {
77 | this(alpha, layout, transform, clipPath, shapes, ByteString.EMPTY);
78 | }
79 |
80 | public FrameEntity(Float alpha, Layout layout, Transform transform, String clipPath, List shapes, ByteString unknownFields) {
81 | super(ADAPTER, unknownFields);
82 | this.alpha = alpha;
83 | this.layout = layout;
84 | this.transform = transform;
85 | this.clipPath = clipPath;
86 | this.shapes = Internal.immutableCopyOf("shapes", shapes);
87 | }
88 |
89 | @Override
90 | public Builder newBuilder() {
91 | Builder builder = new Builder();
92 | builder.alpha = alpha;
93 | builder.layout = layout;
94 | builder.transform = transform;
95 | builder.clipPath = clipPath;
96 | builder.shapes = Internal.copyOf("shapes", shapes);
97 | builder.addUnknownFields(unknownFields());
98 | return builder;
99 | }
100 |
101 | @Override
102 | public boolean equals(Object other) {
103 | if (other == this) return true;
104 | if (!(other instanceof FrameEntity)) return false;
105 | FrameEntity o = (FrameEntity) other;
106 | return unknownFields().equals(o.unknownFields())
107 | && Internal.equals(alpha, o.alpha)
108 | && Internal.equals(layout, o.layout)
109 | && Internal.equals(transform, o.transform)
110 | && Internal.equals(clipPath, o.clipPath)
111 | && shapes.equals(o.shapes);
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | int result = super.hashCode;
117 | if (result == 0) {
118 | result = unknownFields().hashCode();
119 | result = result * 37 + (alpha != null ? alpha.hashCode() : 0);
120 | result = result * 37 + (layout != null ? layout.hashCode() : 0);
121 | result = result * 37 + (transform != null ? transform.hashCode() : 0);
122 | result = result * 37 + (clipPath != null ? clipPath.hashCode() : 0);
123 | result = result * 37 + shapes.hashCode();
124 | super.hashCode = result;
125 | }
126 | return result;
127 | }
128 |
129 | @Override
130 | public String toString() {
131 | StringBuilder builder = new StringBuilder();
132 | if (alpha != null) builder.append(", alpha=").append(alpha);
133 | if (layout != null) builder.append(", layout=").append(layout);
134 | if (transform != null) builder.append(", transform=").append(transform);
135 | if (clipPath != null) builder.append(", clipPath=").append(clipPath);
136 | if (!shapes.isEmpty()) builder.append(", shapes=").append(shapes);
137 | return builder.replace(0, 2, "FrameEntity{").append('}').toString();
138 | }
139 |
140 | public static final class Builder extends Message.Builder {
141 | public Float alpha;
142 |
143 | public Layout layout;
144 |
145 | public Transform transform;
146 |
147 | public String clipPath;
148 |
149 | public List shapes;
150 |
151 | public Builder() {
152 | shapes = Internal.newMutableList();
153 | }
154 |
155 | /**
156 | * 透明度
157 | */
158 | public Builder alpha(Float alpha) {
159 | this.alpha = alpha;
160 | return this;
161 | }
162 |
163 | /**
164 | * 初始约束大小
165 | */
166 | public Builder layout(Layout layout) {
167 | this.layout = layout;
168 | return this;
169 | }
170 |
171 | /**
172 | * 2D 变换矩阵
173 | */
174 | public Builder transform(Transform transform) {
175 | this.transform = transform;
176 | return this;
177 | }
178 |
179 | /**
180 | * 遮罩路径,使用 SVG 标准 Path 绘制图案进行 Mask 遮罩。
181 | */
182 | public Builder clipPath(String clipPath) {
183 | this.clipPath = clipPath;
184 | return this;
185 | }
186 |
187 | /**
188 | * 矢量元素列表
189 | */
190 | public Builder shapes(List shapes) {
191 | Internal.checkElementsNotNull(shapes);
192 | this.shapes = shapes;
193 | return this;
194 | }
195 |
196 | @Override
197 | public FrameEntity build() {
198 | return new FrameEntity(alpha, layout, transform, clipPath, shapes, super.buildUnknownFields());
199 | }
200 | }
201 |
202 | private static final class ProtoAdapter_FrameEntity extends ProtoAdapter {
203 | ProtoAdapter_FrameEntity() {
204 | super(FieldEncoding.LENGTH_DELIMITED, FrameEntity.class);
205 | }
206 |
207 | @Override
208 | public int encodedSize(FrameEntity value) {
209 | return (value.alpha != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.alpha) : 0)
210 | + (value.layout != null ? Layout.ADAPTER.encodedSizeWithTag(2, value.layout) : 0)
211 | + (value.transform != null ? Transform.ADAPTER.encodedSizeWithTag(3, value.transform) : 0)
212 | + (value.clipPath != null ? ProtoAdapter.STRING.encodedSizeWithTag(4, value.clipPath) : 0)
213 | + ShapeEntity.ADAPTER.asRepeated().encodedSizeWithTag(5, value.shapes)
214 | + value.unknownFields().size();
215 | }
216 |
217 | @Override
218 | public void encode(ProtoWriter writer, FrameEntity value) throws IOException {
219 | if (value.alpha != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.alpha);
220 | if (value.layout != null) Layout.ADAPTER.encodeWithTag(writer, 2, value.layout);
221 | if (value.transform != null) Transform.ADAPTER.encodeWithTag(writer, 3, value.transform);
222 | if (value.clipPath != null) ProtoAdapter.STRING.encodeWithTag(writer, 4, value.clipPath);
223 | ShapeEntity.ADAPTER.asRepeated().encodeWithTag(writer, 5, value.shapes);
224 | writer.writeBytes(value.unknownFields());
225 | }
226 |
227 | @Override
228 | public FrameEntity decode(ProtoReader reader) throws IOException {
229 | Builder builder = new Builder();
230 | long token = reader.beginMessage();
231 | for (int tag; (tag = reader.nextTag()) != -1;) {
232 | switch (tag) {
233 | case 1: builder.alpha(ProtoAdapter.FLOAT.decode(reader)); break;
234 | case 2: builder.layout(Layout.ADAPTER.decode(reader)); break;
235 | case 3: builder.transform(Transform.ADAPTER.decode(reader)); break;
236 | case 4: builder.clipPath(ProtoAdapter.STRING.decode(reader)); break;
237 | case 5: builder.shapes.add(ShapeEntity.ADAPTER.decode(reader)); break;
238 | default: {
239 | FieldEncoding fieldEncoding = reader.peekFieldEncoding();
240 | Object value = fieldEncoding.rawProtoAdapter().decode(reader);
241 | builder.addUnknownField(tag, fieldEncoding, value);
242 | }
243 | }
244 | }
245 | reader.endMessage(token);
246 | return builder.build();
247 | }
248 |
249 | @Override
250 | public FrameEntity redact(FrameEntity value) {
251 | Builder builder = value.newBuilder();
252 | if (builder.layout != null) builder.layout = Layout.ADAPTER.redact(builder.layout);
253 | if (builder.transform != null) builder.transform = Transform.ADAPTER.redact(builder.transform);
254 | Internal.redactElements(builder.shapes, ShapeEntity.ADAPTER);
255 | builder.clearUnknownFields();
256 | return builder.build();
257 | }
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/library/src/main/java/com/opensource/svgaplayer/proto/MovieEntity.java:
--------------------------------------------------------------------------------
1 | // Code generated by Wire protocol buffer compiler, do not edit.
2 | // Source file: svga.proto at 123:1
3 | package com.opensource.svgaplayer.proto;
4 |
5 | import com.squareup.wire.FieldEncoding;
6 | import com.squareup.wire.Message;
7 | import com.squareup.wire.ProtoAdapter;
8 | import com.squareup.wire.ProtoReader;
9 | import com.squareup.wire.ProtoWriter;
10 | import com.squareup.wire.WireField;
11 | import com.squareup.wire.internal.Internal;
12 | import java.io.IOException;
13 | import java.lang.Object;
14 | import java.lang.Override;
15 | import java.lang.String;
16 | import java.lang.StringBuilder;
17 | import java.util.List;
18 | import java.util.Map;
19 | import okio.ByteString;
20 |
21 | public final class MovieEntity extends Message {
22 | public static final ProtoAdapter ADAPTER = new ProtoAdapter_MovieEntity();
23 |
24 | private static final long serialVersionUID = 0L;
25 |
26 | public static final String DEFAULT_VERSION = "";
27 |
28 | /**
29 | * SVGA 格式版本号
30 | */
31 | @WireField(
32 | tag = 1,
33 | adapter = "com.squareup.wire.ProtoAdapter#STRING"
34 | )
35 | public final String version;
36 |
37 | /**
38 | * 动画参数
39 | */
40 | @WireField(
41 | tag = 2,
42 | adapter = "com.opensource.svgaplayer.proto.MovieParams#ADAPTER"
43 | )
44 | public final MovieParams params;
45 |
46 | /**
47 | * Key 是位图键名,Value 是位图文件名或二进制 PNG 数据。
48 | */
49 | @WireField(
50 | tag = 3,
51 | keyAdapter = "com.squareup.wire.ProtoAdapter#STRING",
52 | adapter = "com.squareup.wire.ProtoAdapter#BYTES"
53 | )
54 | public final Map images;
55 |
56 | /**
57 | * 元素列表
58 | */
59 | @WireField(
60 | tag = 4,
61 | adapter = "com.opensource.svgaplayer.proto.SpriteEntity#ADAPTER",
62 | label = WireField.Label.REPEATED
63 | )
64 | public final List sprites;
65 |
66 | /**
67 | * 音频列表
68 | */
69 | @WireField(
70 | tag = 5,
71 | adapter = "com.opensource.svgaplayer.proto.AudioEntity#ADAPTER",
72 | label = WireField.Label.REPEATED
73 | )
74 | public final List audios;
75 |
76 | public MovieEntity(String version, MovieParams params, Map images, List sprites, List audios) {
77 | this(version, params, images, sprites, audios, ByteString.EMPTY);
78 | }
79 |
80 | public MovieEntity(String version, MovieParams params, Map images, List sprites, List audios, ByteString unknownFields) {
81 | super(ADAPTER, unknownFields);
82 | this.version = version;
83 | this.params = params;
84 | this.images = Internal.immutableCopyOf("images", images);
85 | this.sprites = Internal.immutableCopyOf("sprites", sprites);
86 | this.audios = Internal.immutableCopyOf("audios", audios);
87 | }
88 |
89 | @Override
90 | public Builder newBuilder() {
91 | Builder builder = new Builder();
92 | builder.version = version;
93 | builder.params = params;
94 | builder.images = Internal.copyOf("images", images);
95 | builder.sprites = Internal.copyOf("sprites", sprites);
96 | builder.audios = Internal.copyOf("audios", audios);
97 | builder.addUnknownFields(unknownFields());
98 | return builder;
99 | }
100 |
101 | @Override
102 | public boolean equals(Object other) {
103 | if (other == this) return true;
104 | if (!(other instanceof MovieEntity)) return false;
105 | MovieEntity o = (MovieEntity) other;
106 | return unknownFields().equals(o.unknownFields())
107 | && Internal.equals(version, o.version)
108 | && Internal.equals(params, o.params)
109 | && images.equals(o.images)
110 | && sprites.equals(o.sprites)
111 | && audios.equals(o.audios);
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | int result = super.hashCode;
117 | if (result == 0) {
118 | result = unknownFields().hashCode();
119 | result = result * 37 + (version != null ? version.hashCode() : 0);
120 | result = result * 37 + (params != null ? params.hashCode() : 0);
121 | result = result * 37 + images.hashCode();
122 | result = result * 37 + sprites.hashCode();
123 | result = result * 37 + audios.hashCode();
124 | super.hashCode = result;
125 | }
126 | return result;
127 | }
128 |
129 | @Override
130 | public String toString() {
131 | StringBuilder builder = new StringBuilder();
132 | if (version != null) builder.append(", version=").append(version);
133 | if (params != null) builder.append(", params=").append(params);
134 | if (!images.isEmpty()) builder.append(", images=").append(images);
135 | if (!sprites.isEmpty()) builder.append(", sprites=").append(sprites);
136 | if (!audios.isEmpty()) builder.append(", audios=").append(audios);
137 | return builder.replace(0, 2, "MovieEntity{").append('}').toString();
138 | }
139 |
140 | public static final class Builder extends Message.Builder {
141 | public String version;
142 |
143 | public MovieParams params;
144 |
145 | public Map images;
146 |
147 | public List sprites;
148 |
149 | public List audios;
150 |
151 | public Builder() {
152 | images = Internal.newMutableMap();
153 | sprites = Internal.newMutableList();
154 | audios = Internal.newMutableList();
155 | }
156 |
157 | /**
158 | * SVGA 格式版本号
159 | */
160 | public Builder version(String version) {
161 | this.version = version;
162 | return this;
163 | }
164 |
165 | /**
166 | * 动画参数
167 | */
168 | public Builder params(MovieParams params) {
169 | this.params = params;
170 | return this;
171 | }
172 |
173 | /**
174 | * Key 是位图键名,Value 是位图文件名或二进制 PNG 数据。
175 | */
176 | public Builder images(Map images) {
177 | Internal.checkElementsNotNull(images);
178 | this.images = images;
179 | return this;
180 | }
181 |
182 | /**
183 | * 元素列表
184 | */
185 | public Builder sprites(List sprites) {
186 | Internal.checkElementsNotNull(sprites);
187 | this.sprites = sprites;
188 | return this;
189 | }
190 |
191 | /**
192 | * 音频列表
193 | */
194 | public Builder audios(List audios) {
195 | Internal.checkElementsNotNull(audios);
196 | this.audios = audios;
197 | return this;
198 | }
199 |
200 | @Override
201 | public MovieEntity build() {
202 | return new MovieEntity(version, params, images, sprites, audios, super.buildUnknownFields());
203 | }
204 | }
205 |
206 | private static final class ProtoAdapter_MovieEntity extends ProtoAdapter {
207 | private final ProtoAdapter