fun parse()

in plot-raster/src/commonMain/kotlin/org/jetbrains/letsPlot/raster/mapping/svg/SvgPathParser.kt [21:133]


    fun parse(): Path2d {
        val path = Path2d()
        var curX = 0.0
        var curY = 0.0
        var currentCommand: Char? = null

        while (index < length) {
            skipWhitespaceAndComma()
            if (index >= length) break

            val char = pathData[index]
            if (char.isLetter()) {
                currentCommand = char
                index++
                skipWhitespaceAndComma()
            }

            when (currentCommand) {
                'M', 'm' -> {
                    if (currentCommand == 'M') {
                        curX = readNumber()
                        curY = readNumber()
                    } else {
                        curX += readNumber()
                        curY += readNumber()
                    }

                    path.moveTo(curX, curY)
                    currentCommand = if (currentCommand == 'M') 'L' else 'l'
                }

                'L', 'l' -> {
                    if (currentCommand == 'L') {
                        curX = readNumber()
                        curY = readNumber()
                    } else {
                        curX += readNumber()
                        curY += readNumber()
                    }
                    path.lineTo(curX, curY)
                }

                'A', 'a' -> {
                    val rx = readNumber()
                    val ry = readNumber()
                    val angle = toRadians(readNumber())
                    val largeArcFlag = readNumber().toInt() != 0
                    val sweepFlag = readNumber().toInt() != 0
                    val x = readNumber()
                    val y = readNumber()

                    val (newX, newY) = when (currentCommand) {
                        'A' -> x to y
                        'a' -> x + curX to y + curY
                        else -> error("Should not happen")
                    }

                    path.arc(
                        x1 = curX, y1 = curY,
                        x2 = newX, y2 = newY,
                        rxIn = rx, ryIn = ry,
                        angle = angle, largeArcFlag = largeArcFlag, sweepFlag = sweepFlag,
                        connect = false // prevent lineTo(x1, y1) generated by Path2d - the curPoint is already there
                    )

                    curX = newX
                    curY = newY
                }

                'H', 'h' -> {
                    if (currentCommand == 'H') {
                        curX = readNumber()
                    } else {
                        curX += readNumber()
                    }
                    path.lineTo(curX, curY)
                }

                'V', 'v' -> {
                    if (currentCommand == 'V') {
                        curY = readNumber()
                    } else {
                        curY += readNumber()
                    }
                    path.lineTo(curX, curY)
                }

                'C', 'c' -> {
                    val (dx, dy) = if (currentCommand == 'C') 0.0 to 0.0 else curX to curY

                    val x1 = readNumber() + dx
                    val y1 = readNumber() + dy
                    val x2 = readNumber() + dx
                    val y2 = readNumber() + dy
                    val x = readNumber() + dx
                    val y = readNumber() + dy

                    path.bezierCurveTo(x1, y1, x2, y2, x, y)
                    curX = x
                    curY = y
                }


                'Z', 'z' -> {
                    path.closePath()
                }

                else -> error("Unsupported command: $currentCommand at position $index")
            }
        }

        return path
    }