美文网首页
SVG path 绝对路径转相对路径

SVG path 绝对路径转相对路径

作者: 熊er | 来源:发表于2020-12-26 13:48 被阅读0次
    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")
            }
        }
    
    }
    

    相关文章

      网友评论

          本文标题:SVG path 绝对路径转相对路径

          本文链接:https://www.haomeiwen.com/subject/obcgnktx.html