parsePath method
ShapePath
parsePath(
- String d
)
Implementation
ShapePath parsePath(String d) {
final path = ShapePath();
final point = Vector2();
final control = Vector2();
final firstPoint = Vector2();
bool isFirstPoint = true;
bool doSetFirstPoint = false;
final reg = RegExp(r"[a-df-z][^a-df-z]*", caseSensitive: false);
final commands = reg.allMatches(d);
// final commands = d.match( /[a-df-z][^a-df-z]*/ig );
for (final item in commands) {
final command = item.group(0)!;
final type = command.substring(0, 1);
final data = substr(command, 1).trim();
if (isFirstPoint == true) {
doSetFirstPoint = true;
isFirstPoint = false;
}
switch (type) {
case 'M':
List<double> numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
point.x = numbers[j + 0];
point.y = numbers[j + 1];
control.x = point.x;
control.y = point.y;
if (j == 0) {
path.moveTo(point.x, point.y);
} else {
path.lineTo(point.x, point.y);
}
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'H':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j++) {
point.x = numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'V':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j++) {
point.y = numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'L':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
point.x = numbers[j + 0];
point.y = numbers[j + 1];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'C':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 6) {
path.bezierCurveTo(numbers[j + 0], numbers[j + 1], numbers[j + 2],
numbers[j + 3], numbers[j + 4], numbers[j + 5]);
control.x = numbers[j + 2];
control.y = numbers[j + 3];
point.x = numbers[j + 4];
point.y = numbers[j + 5];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'S':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 4) {
path.bezierCurveTo(
getReflection(point.x, control.x),
getReflection(point.y, control.y),
numbers[j + 0],
numbers[j + 1],
numbers[j + 2],
numbers[j + 3]);
control.x = numbers[j + 0];
control.y = numbers[j + 1];
point.x = numbers[j + 2];
point.y = numbers[j + 3];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'Q':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 4) {
path.quadraticCurveTo(
numbers[j + 0], numbers[j + 1], numbers[j + 2], numbers[j + 3]);
control.x = numbers[j + 0];
control.y = numbers[j + 1];
point.x = numbers[j + 2];
point.y = numbers[j + 3];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'T':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
final rx = getReflection(point.x, control.x);
final ry = getReflection(point.y, control.y);
path.quadraticCurveTo(rx, ry, numbers[j + 0], numbers[j + 1]);
control.x = rx;
control.y = ry;
point.x = numbers[j + 0];
point.y = numbers[j + 1];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'A':
final numbers = parseFloats(data, [3, 4], 7);
for (int j = 0, jl = numbers.length; j < jl; j += 7) {
// skip command if start point == end point
if (numbers[j + 5] == point.x && numbers[j + 6] == point.y) {
continue;
}
final start = point.clone();
point.x = numbers[j + 5];
point.y = numbers[j + 6];
control.x = point.x;
control.y = point.y;
parseArcCommand(path, numbers[j], numbers[j + 1], numbers[j + 2],
numbers[j + 3], numbers[j + 4], start, point);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'm':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
point.x += numbers[j + 0];
point.y += numbers[j + 1];
control.x = point.x;
control.y = point.y;
if (j == 0) {
path.moveTo(point.x, point.y);
} else {
path.lineTo(point.x, point.y);
}
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'h':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j++) {
point.x += numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'v':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j++) {
point.y += numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'l':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
point.x += numbers[j + 0];
point.y += numbers[j + 1];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'c':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 6) {
path.bezierCurveTo(
point.x + numbers[j + 0],
point.y + numbers[j + 1],
point.x + numbers[j + 2],
point.y + numbers[j + 3],
point.x + numbers[j + 4],
point.y + numbers[j + 5]);
control.x = point.x + numbers[j + 2];
control.y = point.y + numbers[j + 3];
point.x += numbers[j + 4];
point.y += numbers[j + 5];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 's':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 4) {
path.bezierCurveTo(
getReflection(point.x, control.x),
getReflection(point.y, control.y),
point.x + numbers[j + 0],
point.y + numbers[j + 1],
point.x + numbers[j + 2],
point.y + numbers[j + 3]);
control.x = point.x + numbers[j + 0];
control.y = point.y + numbers[j + 1];
point.x += numbers[j + 2];
point.y += numbers[j + 3];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'q':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 4) {
path.quadraticCurveTo(
point.x + numbers[j + 0],
point.y + numbers[j + 1],
point.x + numbers[j + 2],
point.y + numbers[j + 3]);
control.x = point.x + numbers[j + 0];
control.y = point.y + numbers[j + 1];
point.x += numbers[j + 2];
point.y += numbers[j + 3];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 't':
final numbers = parseFloats(data);
for (int j = 0, jl = numbers.length; j < jl; j += 2) {
final rx = getReflection(point.x, control.x);
final ry = getReflection(point.y, control.y);
path.quadraticCurveTo(
rx, ry, point.x + numbers[j + 0], point.y + numbers[j + 1]);
control.x = rx;
control.y = ry;
point.x = point.x + numbers[j + 0];
point.y = point.y + numbers[j + 1];
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'a':
final numbers = parseFloats(data, [3, 4], 7);
for (int j = 0, jl = numbers.length; j < jl; j += 7) {
// skip command if no displacement
if (numbers[j + 5] == 0 && numbers[j + 6] == 0) continue;
final start = point.clone();
point.x += numbers[j + 5];
point.y += numbers[j + 6];
control.x = point.x;
control.y = point.y;
parseArcCommand(path, numbers[j], numbers[j + 1], numbers[j + 2],
numbers[j + 3], numbers[j + 4], start, point);
if (j == 0 && doSetFirstPoint == true) firstPoint.setFrom(point);
}
break;
case 'Z':
case 'z':
path.currentPath.autoClose = true;
if (path.currentPath.curves.isNotEmpty) {
// Reset point to beginning of Path
point.setFrom(firstPoint);
path.currentPath.currentPoint.setFrom(point);
isFirstPoint = true;
}
break;
default:
console.warning("SvgLoader.parsePathNode command is not support ...\nConnamd: $command");
}
// Console.log( type, parseFloats( data ), parseFloats( data ).length )
doSetFirstPoint = false;
}
return path;
}