1 /*
<lambda>null2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.animation.graphics.res
18 
19 import android.animation.TimeInterpolator
20 import android.content.res.Resources
21 import android.util.Xml
22 import android.view.animation.AnticipateOvershootInterpolator
23 import android.view.animation.BounceInterpolator
24 import androidx.compose.animation.core.Easing
25 import androidx.compose.animation.core.FastOutLinearInEasing
26 import androidx.compose.animation.core.FastOutSlowInEasing
27 import androidx.compose.animation.core.LinearEasing
28 import androidx.compose.animation.core.LinearOutSlowInEasing
29 import androidx.compose.animation.graphics.vector.Animator
30 import androidx.compose.animation.graphics.vector.compat.AndroidVectorResources
31 import androidx.compose.animation.graphics.vector.compat.TagObjectAnimator
32 import androidx.compose.animation.graphics.vector.compat.TagSet
33 import androidx.compose.animation.graphics.vector.compat.parseAnimatorSet
34 import androidx.compose.animation.graphics.vector.compat.parseInterpolator
35 import androidx.compose.animation.graphics.vector.compat.parseObjectAnimator
36 import androidx.compose.animation.graphics.vector.compat.seekToStartTag
37 import kotlin.math.PI
38 import kotlin.math.cos
39 import kotlin.math.pow
40 import kotlin.math.sin
41 import org.xmlpull.v1.XmlPullParserException
42 
43 /** Synchronously loads an [Animator] resource. */
44 @Throws(XmlPullParserException::class)
45 internal fun loadAnimatorResource(
46     theme: Resources.Theme? = null,
47     res: Resources,
48     resId: Int
49 ): Animator {
50     val parser = res.getXml(resId)
51     val attrs = Xml.asAttributeSet(parser)
52 
53     parser.seekToStartTag()
54     return when (parser.name) {
55         TagSet -> {
56             parser.parseAnimatorSet(res, theme, attrs)
57         }
58         TagObjectAnimator -> {
59             parser.parseObjectAnimator(res, theme, attrs)
60         }
61         else -> {
62             throw XmlPullParserException("Unknown tag: ${parser.name}")
63         }
64     }
65 }
66 
toEasingnull67 internal fun TimeInterpolator.toEasing() = Easing { x -> getInterpolation(x) }
68 
xnull69 internal val AccelerateDecelerateEasing = Easing { x ->
70     ((cos((x + 1) * Math.PI) / 2.0f) + 0.5f).toFloat()
71 }
72 
xnull73 internal val AccelerateEasing = Easing { x -> x * x }
74 
xnull75 internal fun AccelerateEasing(factor: Float) = Easing { x -> x.pow(factor * 2) }
76 
AnticipateEasingnull77 internal fun AnticipateEasing(tension: Float) = Easing { x ->
78     x * x * ((tension + 1) * x - tension)
79 }
80 
AnticipateOvershootEasingnull81 internal fun AnticipateOvershootEasing(tension: Float, extraTension: Float): Easing =
82     AnticipateOvershootInterpolator(tension, extraTension).toEasing()
83 
84 internal val BounceEasing: Easing = BounceInterpolator().toEasing()
85 
86 internal fun CycleEasing(cycle: Float) = Easing { x -> sin(2 * cycle * PI * x).toFloat() }
87 
xnull88 internal val DecelerateEasing = Easing { x -> 1.0f - (1.0f - x) * (1.0f - x) }
89 
xnull90 internal fun DecelerateEasing(factor: Float) = Easing { x -> 1.0f - (1.0f - x).pow(2 * factor) }
91 
xnull92 internal fun OvershootEasing(tension: Float) = Easing { x ->
93     (x - 1f).let { t -> t * t * ((tension + 1f) * t + tension) + 1f }
94 }
95 
96 private val builtinInterpolators =
97     hashMapOf(
98         android.R.anim.linear_interpolator to LinearEasing,
99         android.R.interpolator.fast_out_linear_in to FastOutLinearInEasing,
100         android.R.interpolator.fast_out_slow_in to FastOutSlowInEasing,
101         android.R.interpolator.linear to LinearEasing,
102         android.R.interpolator.linear_out_slow_in to LinearOutSlowInEasing,
103         AndroidVectorResources.FAST_OUT_LINEAR_IN to FastOutLinearInEasing,
104         AndroidVectorResources.FAST_OUT_SLOW_IN to FastOutSlowInEasing,
105         AndroidVectorResources.LINEAR_OUT_SLOW_IN to LinearOutSlowInEasing
106     )
107 
108 /** Synchronously loads an interpolator resource as an [Easing]. */
109 @Throws(XmlPullParserException::class)
loadInterpolatorResourcenull110 internal fun loadInterpolatorResource(
111     theme: Resources.Theme? = null,
112     res: Resources,
113     resId: Int
114 ): Easing {
115     return builtinInterpolators[resId]
116         ?: res.getXml(resId).run {
117             seekToStartTag().parseInterpolator(res, theme, Xml.asAttributeSet(this))
118         }
119 }
120