import java.math.BigDecimal
private class PointB(var x: BigDecimal, var y: BigDecimal)
private operator fun StringBuilder.plus(str: String?): StringBuilder = append(str)
/*
* @from https://www.jianshu.com/p/8cb39eb265e7
*/
object Absolute2Relative4SVG {
fun path2Relative(path: String): String {
val sb = StringBuilder()
val end = PointB(0.toBigDecimal(), 0.toBigDecimal())
val start = PointB(end.x, end.y)
val pattern = "([MmLlHhVvQqTtCcSsAa][^MmLlHhVvQqTtCcSsAaZz]+|[Zz])".toPattern()
val matcher = pattern.matcher(path)
while (matcher.find()) {
val part = matcher.group()
val type = part[0]
if (type in "Zz") {
sb + "z"
end.x = start.x
end.y = start.y
continue
}
val count = when (type) {
in "HhVv" -> 1
in "MmLlTt" -> 2
in "QqSs" -> 4
in "Cc" -> 6
in "Aa" -> 7
else -> error("Syntax Error")
}
part.drop(1)
.split("[ ,]".toRegex())
.mapNotNull { it.toBigDecimalOrNull() }
.withIndex()
.groupBy { it.index / count } // 切割 - 前后类型相同省略
.map { it.value.let { it.map { it.value } } }
.forEach { sb + transform(type, it, start, end) }
}
return sb.toString()
}
private fun transform(type: Char, ls: List<BigDecimal>, start: PointB, end: PointB): String {
return when (type) {
'm' -> {
"$type${ls.joinToString(",")}".also {
end.x += ls[ls.lastIndex - 1]
end.y += ls.last()
start.x = end.x
start.y = end.y
}
}
'h' -> {
"$type${ls.joinToString(",")}".also {
end.x += ls.last()
}
}
'v' -> {
"$type${ls.joinToString(",")}".also {
end.y += ls.last()
}
}
in "lqtcsa" -> {
"$type${ls.joinToString(",")}".also {
end.x += ls[ls.lastIndex - 1]
end.y += ls.last()
}
}
'M' -> {
val ls2 = ls.mapIndexed { i, v -> v - if (i % 2 == 0) end.x else end.y }
"${type.toLowerCase()}${ls2.joinToString(",")}".also {
end.x = ls[ls.lastIndex - 1]
end.y = ls.last()
start.x = end.x
start.y = end.y
}
}
'H' -> {
val ls2 = ls.map { it - end.x }
"${type.toLowerCase()}${ls2.joinToString(",")}".also {
end.x = ls.last()
}
}
'V' -> {
val ls2 = ls.map { it - end.y }
"${type.toLowerCase()}${ls2.joinToString(",")}".also {
end.y = ls.last()
}
}
'A' -> {
arrayOf(
*ls.dropLast(2).toTypedArray(),
ls[ls.lastIndex - 1] - end.x,
ls.last() - end.y
).let { "${type.toLowerCase()}${it.joinToString(",")}" }.also {
end.x = ls[ls.lastIndex - 1]
end.y = ls.last()
}
}
in "LQTCS" -> {
val ls2 = ls.mapIndexed { i, v -> v - if (i % 2 == 0) end.x else end.y }
"${type.toLowerCase()}${ls2.joinToString(",")}".also {
end.x = ls[ls.lastIndex - 1]
end.y = ls.last()
}
}
else -> error("Syntax Error")
}
}
}
网友评论