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