func decodeDrawing()

in shiny/iconvg/decode.go [435:640]


func decodeDrawing(dst Destination, p printer, src buffer) (mf modeFunc, src1 buffer, err error) {
	var coords [6]float32

	switch opcode := src[0]; {
	case opcode < 0xe0:
		op, nCoords, nReps := "", 0, 1+int(opcode&0x0f)
		switch opcode >> 4 {
		case 0x00, 0x01:
			op = "L (absolute lineTo)"
			nCoords = 2
			nReps = 1 + int(opcode&0x1f)
		case 0x02, 0x03:
			op = "l (relative lineTo)"
			nCoords = 2
			nReps = 1 + int(opcode&0x1f)
		case 0x04:
			op = "T (absolute smooth quadTo)"
			nCoords = 2
		case 0x05:
			op = "t (relative smooth quadTo)"
			nCoords = 2
		case 0x06:
			op = "Q (absolute quadTo)"
			nCoords = 4
		case 0x07:
			op = "q (relative quadTo)"
			nCoords = 4
		case 0x08:
			op = "S (absolute smooth cubeTo)"
			nCoords = 4
		case 0x09:
			op = "s (relative smooth cubeTo)"
			nCoords = 4
		case 0x0a:
			op = "C (absolute cubeTo)"
			nCoords = 6
		case 0x0b:
			op = "c (relative cubeTo)"
			nCoords = 6
		case 0x0c:
			op = "A (absolute arcTo)"
			nCoords = 0
		case 0x0d:
			op = "a (relative arcTo)"
			nCoords = 0
		}

		if p != nil {
			p(src[:1], "%s, %d reps\n", op, nReps)
		}
		src = src[1:]

		for i := 0; i < nReps; i++ {
			if p != nil && i != 0 {
				p(nil, "%s, implicit\n", op)
			}
			var largeArc, sweep bool
			if op[0] != 'A' && op[0] != 'a' {
				src, err = decodeCoordinates(coords[:nCoords], p, src)
				if err != nil {
					return nil, nil, err
				}
			} else {
				// We have an absolute or relative arcTo.
				src, err = decodeCoordinates(coords[:2], p, src)
				if err != nil {
					return nil, nil, err
				}
				coords[2], src, err = decodeAngle(p, src)
				if err != nil {
					return nil, nil, err
				}
				largeArc, sweep, src, err = decodeArcToFlags(p, src)
				if err != nil {
					return nil, nil, err
				}
				src, err = decodeCoordinates(coords[4:6], p, src)
				if err != nil {
					return nil, nil, err
				}
			}

			if dst == nil {
				continue
			}
			switch op[0] {
			case 'L':
				dst.AbsLineTo(coords[0], coords[1])
			case 'l':
				dst.RelLineTo(coords[0], coords[1])
			case 'T':
				dst.AbsSmoothQuadTo(coords[0], coords[1])
			case 't':
				dst.RelSmoothQuadTo(coords[0], coords[1])
			case 'Q':
				dst.AbsQuadTo(coords[0], coords[1], coords[2], coords[3])
			case 'q':
				dst.RelQuadTo(coords[0], coords[1], coords[2], coords[3])
			case 'S':
				dst.AbsSmoothCubeTo(coords[0], coords[1], coords[2], coords[3])
			case 's':
				dst.RelSmoothCubeTo(coords[0], coords[1], coords[2], coords[3])
			case 'C':
				dst.AbsCubeTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5])
			case 'c':
				dst.RelCubeTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5])
			case 'A':
				dst.AbsArcTo(coords[0], coords[1], coords[2], largeArc, sweep, coords[4], coords[5])
			case 'a':
				dst.RelArcTo(coords[0], coords[1], coords[2], largeArc, sweep, coords[4], coords[5])
			}
		}

	case opcode == 0xe1:
		if p != nil {
			p(src[:1], "z (closePath); end path\n")
		}
		src = src[1:]
		if dst != nil {
			dst.ClosePathEndPath()
		}
		return decodeStyling, src, nil

	case opcode == 0xe2:
		if p != nil {
			p(src[:1], "z (closePath); M (absolute moveTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:2], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.ClosePathAbsMoveTo(coords[0], coords[1])
		}

	case opcode == 0xe3:
		if p != nil {
			p(src[:1], "z (closePath); m (relative moveTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:2], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.ClosePathRelMoveTo(coords[0], coords[1])
		}

	case opcode == 0xe6:
		if p != nil {
			p(src[:1], "H (absolute horizontal lineTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:1], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.AbsHLineTo(coords[0])
		}

	case opcode == 0xe7:
		if p != nil {
			p(src[:1], "h (relative horizontal lineTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:1], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.RelHLineTo(coords[0])
		}

	case opcode == 0xe8:
		if p != nil {
			p(src[:1], "V (absolute vertical lineTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:1], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.AbsVLineTo(coords[0])
		}

	case opcode == 0xe9:
		if p != nil {
			p(src[:1], "v (relative vertical lineTo)\n")
		}
		src = src[1:]
		src, err = decodeCoordinates(coords[:1], p, src)
		if err != nil {
			return nil, nil, err
		}
		if dst != nil {
			dst.RelVLineTo(coords[0])
		}

	default:
		return nil, nil, errUnsupportedDrawingOpcode
	}
	return decodeDrawing, src, nil
}