<lambda>null1 package com.airbnb.lottie.compose
2
3 import android.graphics.Matrix
4 import android.graphics.Typeface
5 import androidx.compose.runtime.Composable
6 import androidx.compose.runtime.getValue
7 import androidx.compose.runtime.mutableFloatStateOf
8 import androidx.compose.runtime.mutableStateOf
9 import androidx.compose.runtime.remember
10 import androidx.compose.runtime.setValue
11 import androidx.compose.ui.geometry.Size
12 import androidx.compose.ui.graphics.drawscope.DrawScope
13 import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
14 import androidx.compose.ui.graphics.nativeCanvas
15 import androidx.compose.ui.graphics.painter.Painter
16 import androidx.compose.ui.layout.ScaleFactor
17 import androidx.compose.ui.unit.IntSize
18 import com.airbnb.lottie.AsyncUpdates
19 import com.airbnb.lottie.LottieComposition
20 import com.airbnb.lottie.LottieDrawable
21 import com.airbnb.lottie.RenderMode
22 import kotlin.math.roundToInt
23
24 /**
25 * A composable that makes it easy to create a [LottiePainter] and update its properties.
26 */
27 @Composable
28 fun rememberLottiePainter(
29 composition: LottieComposition? = null,
30 progress: Float = 0f,
31 outlineMasksAndMattes: Boolean = false,
32 applyOpacityToLayers: Boolean = false,
33 enableMergePaths: Boolean = false,
34 renderMode: RenderMode = RenderMode.AUTOMATIC,
35 maintainOriginalImageBounds: Boolean = false,
36 dynamicProperties: LottieDynamicProperties? = null,
37 clipToCompositionBounds: Boolean = true,
38 clipTextToBoundingBox: Boolean = false,
39 fontMap: Map<String, Typeface>? = null,
40 asyncUpdates: AsyncUpdates = AsyncUpdates.AUTOMATIC,
41 ): LottiePainter {
42 val painter = remember { LottiePainter() }
43 painter.composition = composition
44 painter.progress = progress
45 painter.outlineMasksAndMattes = outlineMasksAndMattes
46 painter.applyOpacityToLayers = applyOpacityToLayers
47 painter.enableMergePaths = enableMergePaths
48 painter.renderMode = renderMode
49 painter.maintainOriginalImageBounds = maintainOriginalImageBounds
50 painter.dynamicProperties = dynamicProperties
51 painter.clipToCompositionBounds = clipToCompositionBounds
52 painter.clipTextToBoundingBox = clipTextToBoundingBox
53 painter.fontMap = fontMap
54 painter.asyncUpdates = asyncUpdates
55 return painter
56 }
57
58 /**
59 * A [Painter] that renders a [LottieComposition].
60 */
61 class LottiePainter internal constructor(
62 composition: LottieComposition? = null,
63 progress: Float = 0f,
64 outlineMasksAndMattes: Boolean = false,
65 applyOpacityToLayers: Boolean = false,
66 enableMergePaths: Boolean = false,
67 renderMode: RenderMode = RenderMode.AUTOMATIC,
68 maintainOriginalImageBounds: Boolean = false,
69 dynamicProperties: LottieDynamicProperties? = null,
70 clipToCompositionBounds: Boolean = true,
71 clipTextToBoundingBox: Boolean = false,
72 fontMap: Map<String, Typeface>? = null,
73 asyncUpdates: AsyncUpdates = AsyncUpdates.AUTOMATIC,
74 ) : Painter() {
75 internal var composition by mutableStateOf(composition)
76 internal var progress by mutableFloatStateOf(progress)
77 internal var outlineMasksAndMattes by mutableStateOf(outlineMasksAndMattes)
78 internal var applyOpacityToLayers by mutableStateOf(applyOpacityToLayers)
79 internal var enableMergePaths by mutableStateOf(enableMergePaths)
80 internal var renderMode by mutableStateOf(renderMode)
81 internal var maintainOriginalImageBounds by mutableStateOf(maintainOriginalImageBounds)
82 internal var dynamicProperties by mutableStateOf(dynamicProperties)
83 internal var clipToCompositionBounds by mutableStateOf(clipToCompositionBounds)
84 internal var fontMap by mutableStateOf(fontMap)
85 internal var asyncUpdates by mutableStateOf(asyncUpdates)
86 internal var clipTextToBoundingBox by mutableStateOf(clipTextToBoundingBox)
87
88 private var setDynamicProperties: LottieDynamicProperties? = null
89
90 private val drawable = LottieDrawable()
91 private val matrix = Matrix()
92 override val intrinsicSize: Size
93 get() {
94 val composition = composition ?: return Size.Unspecified
95 return Size(composition.bounds.width().toFloat(), composition.bounds.height().toFloat())
96 }
97
onDrawnull98 override fun DrawScope.onDraw() {
99 val composition = composition ?: return
100 drawIntoCanvas { canvas ->
101 val compositionSize = Size(composition.bounds.width().toFloat(), composition.bounds.height().toFloat())
102 val intSize = IntSize(size.width.roundToInt(), size.height.roundToInt())
103
104 matrix.reset()
105 matrix.preScale(intSize.width / compositionSize.width, intSize.height / compositionSize.height)
106
107 drawable.enableMergePathsForKitKatAndAbove(enableMergePaths)
108 drawable.renderMode = renderMode
109 drawable.asyncUpdates = asyncUpdates
110 drawable.composition = composition
111 drawable.setFontMap(fontMap)
112 if (dynamicProperties !== setDynamicProperties) {
113 setDynamicProperties?.removeFrom(drawable)
114 dynamicProperties?.addTo(drawable)
115 setDynamicProperties = dynamicProperties
116 }
117 drawable.setOutlineMasksAndMattes(outlineMasksAndMattes)
118 drawable.isApplyingOpacityToLayersEnabled = applyOpacityToLayers
119 drawable.maintainOriginalImageBounds = maintainOriginalImageBounds
120 drawable.clipToCompositionBounds = clipToCompositionBounds
121 drawable.clipTextToBoundingBox = clipTextToBoundingBox
122 drawable.progress = progress
123 drawable.setBounds(0, 0, composition.bounds.width(), composition.bounds.height())
124 drawable.draw(canvas.nativeCanvas, matrix)
125 }
126
127 }
128 }
129
timesnull130 private operator fun Size.times(scale: ScaleFactor): IntSize {
131 return IntSize((width * scale.scaleX).toInt(), (height * scale.scaleY).toInt())
132 }
133