Skip to content

Commit aca48e7

Browse files
committed
improves: reuse paths.
1 parent ae14e43 commit aca48e7

File tree

4 files changed

+67
-63
lines changed

4 files changed

+67
-63
lines changed

library/src/main/java/com/opensource/svgaplayer/SVGACanvasDrawer.kt

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.R.attr.x
1313
class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicEntity, val canvas: Canvas) : SGVADrawer(videoItem) {
1414

1515
val sharedPaint = Paint()
16+
val sharedPath = Path()
1617
val sharedContentTransform = Matrix()
1718

1819
override fun drawFrame(frameIndex: Int) {
@@ -93,70 +94,32 @@ class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
9394
sharedContentTransform.preConcat(sprite.frameEntity.transform)
9495
sprite.frameEntity.shapes.forEach {
9596
val shape = it
96-
var finalPath = Path()
97-
if (shape.type == SVGAVideoShapeEntity.Type.shape) {
98-
(shape.args?.get("d") as? String)?.let {
99-
SVGAPath(it).path?.let {
100-
finalPath = it
101-
}
102-
}
103-
}
104-
else if (shape.type == SVGAVideoShapeEntity.Type.ellipse) {
105-
val xv = shape.args?.get("x") as? Number ?: return
106-
val yv = shape.args?.get("y") as? Number ?: return
107-
val rxv = shape.args?.get("radiusX") as? Number ?: return
108-
val ryv = shape.args?.get("radiusY") as? Number ?: return
109-
val x = xv.toFloat()
110-
val y = yv.toFloat()
111-
val rx = rxv.toFloat()
112-
val ry = ryv.toFloat()
113-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
114-
finalPath.addOval(x - rx, y - ry, x + rx, y + ry, Path.Direction.CW)
115-
}
116-
else if (Math.abs(rx - ry) < 0.1) {
117-
finalPath.addCircle(x, y, rx, Path.Direction.CW)
118-
}
119-
}
120-
else if (shape.type == SVGAVideoShapeEntity.Type.rect) {
121-
val xv = shape.args?.get("x") as? Number ?: return
122-
val yv = shape.args?.get("y") as? Number ?: return
123-
val wv = shape.args?.get("width") as? Number ?: return
124-
val hv = shape.args?.get("height") as? Number ?: return
125-
val crv = shape.args?.get("cornerRadius") as? Number ?: return
126-
val x = xv.toFloat()
127-
val y = yv.toFloat()
128-
val width = wv.toFloat()
129-
val height = hv.toFloat()
130-
val cornerRadius = crv.toFloat()
131-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
132-
finalPath.addRoundRect(x, y, x + width, y + height, cornerRadius, cornerRadius, Path.Direction.CW)
133-
}
134-
else {
135-
finalPath.addRect(x, y, x + width, y + height, Path.Direction.CW)
136-
}
97+
sharedPath.reset()
98+
shape.shapePath?.let {
99+
sharedPath.addPath(it)
137100
}
138-
if (finalPath != null) {
101+
if (!sharedPath.isEmpty) {
139102
val thisTransform = Matrix()
140103
shape.transform?.let {
141104
thisTransform.postConcat(it)
142105
}
143106
thisTransform.postConcat(sharedContentTransform)
144-
finalPath.transform(thisTransform)
107+
sharedPath.transform(thisTransform)
145108
shape.styles?.fill?.let {
146109
if (it != 0x00000000) {
147110
sharedPaint.reset()
148111
sharedPaint.color = it
149112
sharedPaint.alpha = (sprite.frameEntity.alpha * 255).toInt()
150113
sharedPaint.isAntiAlias = true
151-
canvas.drawPath(finalPath, sharedPaint)
114+
canvas.drawPath(sharedPath, sharedPaint)
152115
}
153116
}
154117
shape.styles?.strokeWidth?.let {
155118
if (it > 0) {
156119
sharedPaint.reset()
157120
sharedPaint.alpha = (sprite.frameEntity.alpha * 255).toInt()
158121
resetShapeStrokePaint(shape)
159-
canvas.drawPath(finalPath, sharedPaint)
122+
canvas.drawPath(sharedPath, sharedPaint)
160123
}
161124
}
162125
}

library/src/main/java/com/opensource/svgaplayer/SVGAPath.kt

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
package com.opensource.svgaplayer
22

33
import android.graphics.Path
4-
5-
import java.io.Serializable
6-
import java.util.ArrayList
7-
import java.util.Arrays
8-
import java.util.Collections
4+
import java.util.*
95

106
internal class SVGAPath {
117

128
val VALID_METHODS: List<String> = listOf("M", "L", "H", "V", "C", "S", "Q", "R", "A", "Z", "m", "l", "h", "v", "c", "s", "q", "r", "a", "z")
139

14-
var path: Path? = null
15-
private set
16-
17-
constructor(strValue: String) {
18-
buildPath(strValue.split("[,\\s+]".toRegex()).dropLastWhile(String::isEmpty).toTypedArray())
10+
constructor(strValue: String, toPath: Path) {
11+
buildPath(strValue.split("[,\\s+]".toRegex()).dropLastWhile(String::isEmpty).toTypedArray(), toPath)
1912
}
2013

21-
private fun buildPath(items: Array<String>) {
22-
val finalPath = Path()
14+
private fun buildPath(items: Array<String>, toPath: Path) {
2315
var currentMethod = ""
2416
val args = ArrayList<SVGAPoint>()
2517
var argLast: String? = null
@@ -32,7 +24,7 @@ internal class SVGAPath {
3224
argLast?.takeIf { it.isNotEmpty() }?.let {
3325
args.add(SVGAPoint(0.0f, 0.0f, try {it.toFloat()} catch (e: Exception) { 0.0f }))
3426
}
35-
this.operate(finalPath, currentMethod, args)
27+
this.operate(toPath, currentMethod, args)
3628
args.clear()
3729
currentMethod = firstLetter
3830
argLast = item.substring(1)
@@ -49,8 +41,7 @@ internal class SVGAPath {
4941
}
5042
}
5143
}
52-
this.operate(finalPath, currentMethod, args)
53-
path = finalPath
44+
this.operate(toPath, currentMethod, args)
5445
}
5546

5647
private fun operate(finalPath: Path, method: String, args: List<SVGAPoint>) {

library/src/main/java/com/opensource/svgaplayer/SVGAVideoShapeEntity.kt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.opensource.svgaplayer
22

33
import android.graphics.Color
44
import android.graphics.Matrix
5+
import android.graphics.Path
6+
import android.os.Build
57

68
import org.json.JSONArray
79
import org.json.JSONException
@@ -64,11 +66,14 @@ class SVGAVideoShapeEntity(obj: JSONObject) {
6466
parseArgs(obj)
6567
parseStyles(obj)
6668
parseTransform(obj)
69+
buildPath()
6770
}
6871

6972
val isKeep: Boolean
7073
get() = type == Type.keep
7174

75+
var shapePath: Path? = null
76+
7277
fun parseType(obj: JSONObject) {
7378
obj.optString("type")?.let {
7479
if (it.equals("shape", ignoreCase = true)) {
@@ -148,4 +153,48 @@ class SVGAVideoShapeEntity(obj: JSONObject) {
148153
}
149154
}
150155

156+
fun buildPath() {
157+
val aPath = Path()
158+
if (this.type == SVGAVideoShapeEntity.Type.shape) {
159+
(this.args?.get("d") as? String)?.let {
160+
SVGAPath(it, aPath)
161+
}
162+
}
163+
else if (this.type == SVGAVideoShapeEntity.Type.ellipse) {
164+
val xv = this.args?.get("x") as? Number ?: return
165+
val yv = this.args?.get("y") as? Number ?: return
166+
val rxv = this.args?.get("radiusX") as? Number ?: return
167+
val ryv = this.args?.get("radiusY") as? Number ?: return
168+
val x = xv.toFloat()
169+
val y = yv.toFloat()
170+
val rx = rxv.toFloat()
171+
val ry = ryv.toFloat()
172+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
173+
aPath.addOval(x - rx, y - ry, x + rx, y + ry, Path.Direction.CW)
174+
}
175+
else if (Math.abs(rx - ry) < 0.1) {
176+
aPath.addCircle(x, y, rx, Path.Direction.CW)
177+
}
178+
}
179+
else if (this.type == SVGAVideoShapeEntity.Type.rect) {
180+
val xv = this.args?.get("x") as? Number ?: return
181+
val yv = this.args?.get("y") as? Number ?: return
182+
val wv = this.args?.get("width") as? Number ?: return
183+
val hv = this.args?.get("height") as? Number ?: return
184+
val crv = this.args?.get("cornerRadius") as? Number ?: return
185+
val x = xv.toFloat()
186+
val y = yv.toFloat()
187+
val width = wv.toFloat()
188+
val height = hv.toFloat()
189+
val cornerRadius = crv.toFloat()
190+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
191+
aPath.addRoundRect(x, y, x + width, y + height, cornerRadius, cornerRadius, Path.Direction.CW)
192+
}
193+
else {
194+
aPath.addRect(x, y, x + width, y + height, Path.Direction.CW)
195+
}
196+
}
197+
this.shapePath = aPath
198+
}
199+
151200
}

library/src/main/java/com/opensource/svgaplayer/SVGAVideoSpriteFrameEntity.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ class SVGAVideoSpriteFrameEntity(obj: JSONObject) {
4444
arr[8] = 1.0.toFloat()
4545
transform.setValues(arr)
4646
}
47-
obj.optString("clipPath")?.let {
48-
if (it.isNotEmpty()) {
49-
maskPath = SVGAPath(it).path
47+
obj.optString("clipPath")?.let { d ->
48+
if (d.isNotEmpty()) {
49+
maskPath = Path()
50+
maskPath?.let { maskPath -> SVGAPath(d, maskPath) }
5051
}
5152
}
5253
obj.optJSONArray("shapes")?.let {

0 commit comments

Comments
 (0)