func upgradeDrawing()

in shiny/iconvg/upgrade.go [337:491]


func upgradeDrawing(u *upgrader, v1 buffer, v0 buffer) (uf upgradeFunc, newV1 buffer, newV0 buffer, retErr error) {
	u.verbs = u.verbs[:0]
	u.args = u.args[:0]

	coords := [3][2]float32{}
	pen := [2]float32{}
	prevSmoothType := smoothTypeNone
	prevSmoothPoint := [2]float32{}

	// Handle the implicit M after a "Start path" styling op.
	v0, retErr = decodeCoordinates(pen[:2], nil, v0)
	if retErr != nil {
		return nil, nil, nil, retErr
	}
	u.verbs = append(u.verbs, upgradeVerbMoveTo)
	u.args = append(u.args, pen)
	startingPoint := pen

	for len(v0) > 0 {
		switch opcode := v0[0]; {
		case opcode < 0xc0: // LineTo, QuadTo, CubeTo.
			nCoordPairs, nReps, relative, smoothType := 0, 1+int(opcode&0x0f), false, smoothTypeNone
			switch opcode >> 4 {
			case 0x00, 0x01: // "L (absolute lineTo)"
				nCoordPairs = 1
				nReps = 1 + int(opcode&0x1f)
			case 0x02, 0x03: // "l (relative lineTo)"
				nCoordPairs = 1
				nReps = 1 + int(opcode&0x1f)
				relative = true
			case 0x04: // "T (absolute smooth quadTo)"
				nCoordPairs = 1
				smoothType = smoothTypeQuad
			case 0x05: // "t (relative smooth quadTo)"
				nCoordPairs = 1
				relative = true
				smoothType = smoothTypeQuad
			case 0x06: // "Q (absolute quadTo)"
				nCoordPairs = 2
			case 0x07: // "q (relative quadTo)"
				nCoordPairs = 2
				relative = true
			case 0x08: // "S (absolute smooth cubeTo)"
				nCoordPairs = 2
				smoothType = smoothTypeCube
			case 0x09: // "s (relative smooth cubeTo)"
				nCoordPairs = 2
				relative = true
				smoothType = smoothTypeCube
			case 0x0a: // "C (absolute cubeTo)"
				nCoordPairs = 3
			case 0x0b: // "c (relative cubeTo)"
				nCoordPairs = 3
				relative = true
			}
			v0 = v0[1:]

			for i := 0; i < nReps; i++ {
				smoothIndex := 0
				if smoothType != smoothTypeNone {
					smoothIndex = 1
					if smoothType != prevSmoothType {
						coords[0][0] = pen[0]
						coords[0][1] = pen[1]
					} else {
						coords[0][0] = (2 * pen[0]) - prevSmoothPoint[0]
						coords[0][1] = (2 * pen[1]) - prevSmoothPoint[1]
					}
				}
				allCoords := coords[:smoothIndex+nCoordPairs]
				explicitCoords := allCoords[smoothIndex:]

				v0, retErr = decodeCoordinatePairs(explicitCoords, nil, v0)
				if retErr != nil {
					return nil, nil, nil, retErr
				}
				if relative {
					for c := range explicitCoords {
						explicitCoords[c][0] += pen[0]
						explicitCoords[c][1] += pen[1]
					}
				}

				u.verbs = append(u.verbs, uint8(len(allCoords)))
				u.args = append(u.args, allCoords...)

				pen = allCoords[len(allCoords)-1]
				if len(allCoords) == 2 {
					prevSmoothPoint = allCoords[0]
					prevSmoothType = smoothTypeQuad
				} else if len(allCoords) == 3 {
					prevSmoothPoint = allCoords[1]
					prevSmoothType = smoothTypeCube
				} else {
					prevSmoothType = smoothTypeNone
				}
			}

		case opcode < 0xe0: // ArcTo.
			v1, v0, retErr = u.upgradeArcs(&pen, v1, v0)
			if retErr != nil {
				return nil, nil, nil, retErr
			}
			prevSmoothType = smoothTypeNone

		default: // Other drawing opcodes.
			v0 = v0[1:]
			switch opcode {
			case 0xe1: // "z (closePath); end path"
				goto endPath

			case 0xe2, 0xe3: // "z (closePath); M (absolute/relative moveTo)"
				v0, retErr = decodeCoordinatePairs(coords[:1], nil, v0)
				if retErr != nil {
					return nil, nil, nil, retErr
				}
				if opcode == 0xe2 {
					pen[0] = coords[0][0]
					pen[1] = coords[0][1]
				} else {
					pen[0] += coords[0][0]
					pen[1] += coords[0][1]
				}
				u.verbs = append(u.verbs, upgradeVerbMoveTo)
				u.args = append(u.args, pen)

			default:
				tmp := [1]float32{}
				v0, retErr = decodeCoordinates(tmp[:1], nil, v0)
				if retErr != nil {
					return nil, nil, nil, retErr
				}
				switch opcode {
				case 0xe6: // "H (absolute horizontal lineTo)"
					pen[0] = tmp[0]
				case 0xe7: // "h (relative horizontal lineTo)"
					pen[0] += tmp[0]
				case 0xe8: // "V (absolute vertical lineTo)"
					pen[1] = tmp[0]
				case 0xe9: // "v (relative vertical lineTo)"
					pen[1] += tmp[0]
				default:
					return nil, nil, nil, errUnsupportedDrawingOpcode
				}
				u.verbs = append(u.verbs, upgradeVerbLineTo)
				u.args = append(u.args, pen)
			}
			prevSmoothType = smoothTypeNone
		}
	}

endPath:
	v1, retErr = u.finishDrawing(v1, startingPoint)
	return upgradeStyling, v1, v0, retErr
}