export function renderPath()

in packages/util-shapes/src/render.ts [24:308]


export function renderPath(context: any, path: any, l: any, t: any, s: any) {
	let current // current instruction
	let previous = null
	let x = 0 // current x
	let y = 0 // current y
	let controlX = 0 // current control point x
	let controlY = 0 // current control point y
	let tempX
	let tempY
	let tempControlX
	let tempControlY

	if (l == null) {
		l = 0
	}
	if (t == null) {
		t = 0
	}
	if (s == null) {
		s = 1
	}

	if (context.beginPath) {
		context.beginPath()
	}

	for (let i = 0, len = path.length; i < len; ++i) {
		current = path[i]
		if (s !== 1) {
			current = scale(current, s)
		}

		switch (
			current[0] // first letter
		) {
			case 'l': // lineto, relative
				x += current[1]
				y += current[2]
				context.lineTo(x + l, y + t)
				break

			case 'L': // lineto, absolute
				x = current[1]
				y = current[2]
				context.lineTo(x + l, y + t)
				break

			case 'h': // horizontal lineto, relative
				x += current[1]
				context.lineTo(x + l, y + t)
				break

			case 'H': // horizontal lineto, absolute
				x = current[1]
				context.lineTo(x + l, y + t)
				break

			case 'v': // vertical lineto, relative
				y += current[1]
				context.lineTo(x + l, y + t)
				break

			case 'V': // verical lineto, absolute
				y = current[1]
				context.lineTo(x + l, y + t)
				break

			case 'm': // moveTo, relative
				x += current[1]
				y += current[2]
				context.moveTo(x + l, y + t)
				break

			case 'M': // moveTo, absolute
				x = current[1]
				y = current[2]
				context.moveTo(x + l, y + t)
				break

			case 'c': // bezierCurveTo, relative
				tempX = x + current[5]
				tempY = y + current[6]
				controlX = x + current[3]
				controlY = y + current[4]
				context.bezierCurveTo(
					x + current[1] + l, // x1
					y + current[2] + t, // y1
					controlX + l, // x2
					controlY + t, // y2
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				break

			case 'C': // bezierCurveTo, absolute
				x = current[5]
				y = current[6]
				controlX = current[3]
				controlY = current[4]
				context.bezierCurveTo(
					current[1] + l,
					current[2] + t,
					controlX + l,
					controlY + t,
					x + l,
					y + t,
				)
				break

			case 's': // shorthand cubic bezierCurveTo, relative
				// transform to absolute x,y
				tempX = x + current[3]
				tempY = y + current[4]
				// calculate reflection of previous control points
				controlX = 2 * x - controlX
				controlY = 2 * y - controlY
				context.bezierCurveTo(
					controlX + l,
					controlY + t,
					x + current[1] + l,
					y + current[2] + t,
					tempX + l,
					tempY + t,
				)

				// set control point to 2nd one of this command
				// the first control point is assumed to be the reflection of
				// the second control point on the previous command relative
				// to the current point.
				controlX = x + current[1]
				controlY = y + current[2]

				x = tempX
				y = tempY
				break

			case 'S': // shorthand cubic bezierCurveTo, absolute
				tempX = current[3]
				tempY = current[4]
				// calculate reflection of previous control points
				controlX = 2 * x - controlX
				controlY = 2 * y - controlY
				context.bezierCurveTo(
					controlX + l,
					controlY + t,
					current[1] + l,
					current[2] + t,
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				// set control point to 2nd one of this command
				// the first control point is assumed to be the reflection of
				// the second control point on the previous command relative
				// to the current point.
				controlX = current[1]
				controlY = current[2]

				break

			case 'q': // quadraticCurveTo, relative
				// transform to absolute x,y
				tempX = x + current[3]
				tempY = y + current[4]

				controlX = x + current[1]
				controlY = y + current[2]

				context.quadraticCurveTo(
					controlX + l,
					controlY + t,
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				break

			case 'Q': // quadraticCurveTo, absolute
				tempX = current[3]
				tempY = current[4]

				context.quadraticCurveTo(
					current[1] + l,
					current[2] + t,
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				controlX = current[1]
				controlY = current[2]
				break

			case 't': // shorthand quadraticCurveTo, relative
				// transform to absolute x,y
				tempX = x + current[1]
				tempY = y + current[2]

				if (previous[0].match(/[QqTt]/) === null) {
					// If there is no previous command or if the previous command was not a Q, q, T or t,
					// assume the control point is coincident with the current point
					controlX = x
					controlY = y
				} else if (previous[0] === 't') {
					// calculate reflection of previous control points for t
					controlX = 2 * x - (tempControlX as number)
					controlY = 2 * y - (tempControlY as number)
				} else if (previous[0] === 'q') {
					// calculate reflection of previous control points for q
					controlX = 2 * x - controlX
					controlY = 2 * y - controlY
				}

				tempControlX = controlX
				tempControlY = controlY

				context.quadraticCurveTo(
					controlX + l,
					controlY + t,
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				controlX = x + current[1]
				controlY = y + current[2]
				break

			case 'T':
				tempX = current[1]
				tempY = current[2]

				// calculate reflection of previous control points
				controlX = 2 * x - controlX
				controlY = 2 * y - controlY
				context.quadraticCurveTo(
					controlX + l,
					controlY + t,
					tempX + l,
					tempY + t,
				)
				x = tempX
				y = tempY
				break

			case 'a':
				drawArc(context, x + l, y + t, [
					current[1],
					current[2],
					current[3],
					current[4],
					current[5],
					current[6] + x + l,
					current[7] + y + t,
				])
				x += current[6]
				y += current[7]
				break

			case 'A':
				drawArc(context, x + l, y + t, [
					current[1],
					current[2],
					current[3],
					current[4],
					current[5],
					current[6] + l,
					current[7] + t,
				])
				x = current[6]
				y = current[7]
				break

			case 'z':
			case 'Z':
				context.closePath()
				break
		}
		previous = current
	}
}