Make Arc const
This commit is contained in:
@@ -274,21 +274,19 @@ class Arc extends SvgPath {
|
||||
final num rotation;
|
||||
final bool arc;
|
||||
final bool sweep;
|
||||
late final num radiusScale;
|
||||
late final Point center;
|
||||
late final num theta;
|
||||
late final num delta;
|
||||
// late final num radiusScale;
|
||||
// late final Point center;
|
||||
// late final num theta;
|
||||
// late num delta;
|
||||
|
||||
Arc({
|
||||
const Arc({
|
||||
required Point start,
|
||||
required Point end,
|
||||
required this.radius,
|
||||
required this.rotation,
|
||||
required this.arc,
|
||||
required this.sweep,
|
||||
}) : super(start: start, end: end) {
|
||||
_parameterize();
|
||||
}
|
||||
}) : super(start: start, end: end);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
@@ -311,68 +309,53 @@ class Arc extends SvgPath {
|
||||
String toString() => 'Arc(start=$start, radius=$radius, rotation=$rotation, '
|
||||
'arc=$arc, sweep=$sweep, end=$end)';
|
||||
|
||||
/// Conversion from endpoint to center parameterization
|
||||
/// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
|
||||
void _parameterize() {
|
||||
// This is equivalent of omitting the segment, so do nothing
|
||||
if (start == end) return;
|
||||
|
||||
// This should be treated as a straight line
|
||||
if (radius.x == 0 || radius.y == 0) return;
|
||||
// Conversion from endpoint to center parameterization
|
||||
// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
|
||||
num get _cosr => cos(radians(rotation));
|
||||
num get _sinr => sin(radians(rotation));
|
||||
num get _dx => (start.x - end.x) / 2;
|
||||
num get _dy => (start.y - end.y) / 2;
|
||||
num get _x1prim => _cosr * _dx + _sinr * _dy;
|
||||
num get _x1primSq => _x1prim * _x1prim;
|
||||
num get _y1prim => -_sinr * _dx + _cosr * _dy;
|
||||
num get _y1primSq => _y1prim * _y1prim;
|
||||
num get _rx => (radiusScale > 1 ? radiusScale : 1) * radius.x;
|
||||
num get _ry => (radiusScale > 1 ? radiusScale : 1) * radius.y;
|
||||
num get _rxSq => _rx * _rx;
|
||||
num get _rySq => _ry * _ry;
|
||||
num get _ux => (_x1prim - _cxprim) / _rx;
|
||||
num get _uy => (_y1prim - _cyprim) / _ry;
|
||||
num get _vx => (-_x1prim - _cxprim) / _rx;
|
||||
num get _vy => (-_y1prim - _cyprim) / _ry;
|
||||
num get t1 => _rxSq * _y1primSq;
|
||||
num get t2 => _rySq * _x1primSq;
|
||||
num get c =>
|
||||
(arc == sweep ? 1 : -1) *
|
||||
sqrt(((_rxSq * _rySq - t1 - t2) / (t1 + t2)).abs());
|
||||
num get _cxprim => c * _rx * _y1prim / _ry;
|
||||
num get _cyprim => -c * _ry * _x1prim / _rx;
|
||||
|
||||
final cosr = cos(radians(rotation));
|
||||
final sinr = sin(radians(rotation));
|
||||
final dx = (start.x - end.x) / 2;
|
||||
final dy = (start.y - end.y) / 2;
|
||||
final x1prim = cosr * dx + sinr * dy;
|
||||
final x1primSq = x1prim * x1prim;
|
||||
final y1prim = -sinr * dx + cosr * dy;
|
||||
final y1primSq = y1prim * y1prim;
|
||||
num get radiusScale {
|
||||
final rs = (_x1primSq / (radius.x * radius.x)) +
|
||||
(_y1primSq / (radius.y * radius.y));
|
||||
return rs > 1 ? sqrt(rs) : 1;
|
||||
}
|
||||
|
||||
num rx = radius.x;
|
||||
num rxSq = rx * rx;
|
||||
num ry = radius.y;
|
||||
num rySq = ry * ry;
|
||||
Point get center => Point(
|
||||
(_cosr * _cxprim - _sinr * _cyprim) + ((start.x + end.x) / 2),
|
||||
(_sinr * _cxprim + _cosr * _cyprim) + ((start.y + end.y) / 2),
|
||||
);
|
||||
|
||||
num get theta {
|
||||
final num n = sqrt(_ux * _ux + _uy * _uy);
|
||||
final num p = _ux;
|
||||
return (((_uy < 0) ? -1 : 1) * degrees(acos(p / n))) % 360;
|
||||
}
|
||||
|
||||
// Correct out of range radii
|
||||
num radiusScale = (x1primSq / rxSq) + (y1primSq / rySq);
|
||||
if (radiusScale > 1) {
|
||||
radiusScale = sqrt(radiusScale);
|
||||
rx *= radiusScale;
|
||||
ry *= radiusScale;
|
||||
rxSq = rx * rx;
|
||||
rySq = ry * ry;
|
||||
this.radiusScale = radiusScale;
|
||||
} else {
|
||||
// SVG spec only scales UP
|
||||
this.radiusScale = 1;
|
||||
}
|
||||
|
||||
final t1 = rxSq * y1primSq;
|
||||
final t2 = rySq * x1primSq;
|
||||
num c = sqrt(((rxSq * rySq - t1 - t2) / (t1 + t2)).abs());
|
||||
|
||||
if (arc == sweep) {
|
||||
c = -c;
|
||||
}
|
||||
final cxprim = c * rx * y1prim / ry;
|
||||
final cyprim = -c * ry * x1prim / rx;
|
||||
|
||||
center = Point(
|
||||
(cosr * cxprim - sinr * cyprim) + ((start.x + end.x) / 2),
|
||||
(sinr * cxprim + cosr * cyprim) + ((start.y + end.y) / 2),
|
||||
);
|
||||
|
||||
final ux = (x1prim - cxprim) / rx;
|
||||
final uy = (y1prim - cyprim) / ry;
|
||||
final vx = (-x1prim - cxprim) / rx;
|
||||
final vy = (-y1prim - cyprim) / ry;
|
||||
num n = sqrt(ux * ux + uy * uy);
|
||||
num p = ux;
|
||||
theta = (((uy < 0) ? -1 : 1) * degrees(acos(p / n))) % 360;
|
||||
|
||||
n = sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
|
||||
p = ux * vx + uy * vy;
|
||||
num get delta {
|
||||
final num n = sqrt((_ux * _ux + _uy * _uy) * (_vx * _vx + _vy * _vy));
|
||||
final num p = _ux * _vx + _uy * _vy;
|
||||
num d = p / n;
|
||||
// In certain cases the above calculation can through inaccuracies
|
||||
// become just slightly out of range, f ex -1.0000000000000002.
|
||||
@@ -381,8 +364,8 @@ class Arc extends SvgPath {
|
||||
} else if (d < -1.0) {
|
||||
d = -1.0;
|
||||
}
|
||||
delta = ((((ux * vy - uy * vx) < 0) ? -1 : 1) * degrees(acos(d))) % 360;
|
||||
if (!sweep) delta -= 360;
|
||||
|
||||
return ((((_ux * _vy - _uy * _vx) < 0) ? -1 : 1) * degrees(acos(d))) % 360 - (!sweep ? 360 : 0);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -448,7 +431,6 @@ class Arc extends SvgPath {
|
||||
class Move extends SvgPath {
|
||||
const Move({required Point to}) : super(start: to, end: to);
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is Move && super == other;
|
||||
|
||||
@@ -472,7 +454,6 @@ class Close extends Linear {
|
||||
required Point end,
|
||||
}) : super(start: start, end: end);
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is Close && super == other;
|
||||
|
||||
|
@@ -88,182 +88,259 @@ void main() {
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M100,800 C175,700 325,700 400,800")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(100 + 800j),
|
||||
// CubicBezier(100 + 800j, 175 + 700j, 325 + 700j, 400 + 800j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M100,800 C175,700 325,700 400,800");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(100, 800)),
|
||||
CubicBezier(
|
||||
start: Point(100, 800),
|
||||
control1: Point(175, 700),
|
||||
control2: Point(325, 700),
|
||||
end: Point(400, 800),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M600,200 C675,100 975,100 900,200")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(600 + 200j),
|
||||
// CubicBezier(600 + 200j, 675 + 100j, 975 + 100j, 900 + 200j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M600,200 C675,100 975,100 900,200");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(600, 200)),
|
||||
CubicBezier(
|
||||
start: Point(600, 200),
|
||||
control1: Point(675, 100),
|
||||
control2: Point(975, 100),
|
||||
end: Point(900, 200),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M600,500 C600,350 900,650 900,500")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(600 + 500j),
|
||||
// CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M600,500 C600,350 900,650 900,500");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(600, 500)),
|
||||
CubicBezier(
|
||||
start: Point(600, 500),
|
||||
control1: Point(600, 350),
|
||||
control2: Point(900, 650),
|
||||
end: Point(900, 500),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path(
|
||||
// """M600,800 C625,700 725,700 750,800
|
||||
// S875,900 900,800"""
|
||||
// )
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(600 + 800j),
|
||||
// CubicBezier(600 + 800j, 625 + 700j, 725 + 700j, 750 + 800j),
|
||||
// CubicBezier(750 + 800j, 775 + 900j, 875 + 900j, 900 + 800j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("""M600,800 C625,700 725,700 750,800
|
||||
S875,900 900,800""");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(600, 800)),
|
||||
CubicBezier(
|
||||
start: Point(600, 800),
|
||||
control1: Point(625, 700),
|
||||
control2: Point(725, 700),
|
||||
end: Point(750, 800)),
|
||||
CubicBezier(
|
||||
start: Point(750, 800),
|
||||
control1: Point(775, 900),
|
||||
control2: Point(875, 900),
|
||||
end: Point(900, 800),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M200,300 Q400,50 600,300 T1000,300")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(200 + 300j),
|
||||
// QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j),
|
||||
// QuadraticBezier(600 + 300j, 800 + 550j, 1000 + 300j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M200,300 Q400,50 600,300 T1000,300");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(200, 300)),
|
||||
QuadraticBezier(
|
||||
start: Point(200, 300),
|
||||
control: Point(400, 50),
|
||||
end: Point(600, 300),
|
||||
),
|
||||
QuadraticBezier(
|
||||
start: Point(600, 300),
|
||||
control: Point(800, 550),
|
||||
end: Point(1000, 300),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M300,200 h-150 a150,150 0 1,0 150,-150 z")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(300 + 200j),
|
||||
// Line(300 + 200j, 150 + 200j),
|
||||
// Arc(150 + 200j, 150 + 150j, 0, 1, 0, 300 + 50j),
|
||||
// Close(300 + 50j, 300 + 200j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M300,200 h-150 a150,150 0 1,0 150,-150 z");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(300, 200)),
|
||||
Line(start: Point(300, 200), end: Point(150, 200)),
|
||||
Arc(
|
||||
start: Point(150, 200),
|
||||
radius: Point(150, 150),
|
||||
rotation: 0,
|
||||
arc: true,
|
||||
sweep: false,
|
||||
end: Point(300, 50),
|
||||
),
|
||||
Close(start: Point(300, 50), end: Point(300, 200)),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M275,175 v-150 a150,150 0 0,0 -150,150 z")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(275 + 175j),
|
||||
// Line(275 + 175j, 275 + 25j),
|
||||
// Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j),
|
||||
// Close(125 + 175j, 275 + 175j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M275,175 v-150 a150,150 0 0,0 -150,150 z");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(275, 175)),
|
||||
Line(start: Point(275, 175), end: Point(275, 25)),
|
||||
Arc(
|
||||
start: Point(275, 25),
|
||||
radius: Point(150, 150),
|
||||
rotation: 0,
|
||||
arc: false,
|
||||
sweep: false,
|
||||
end: Point(125, 175),
|
||||
),
|
||||
Close(start: Point(125, 175), end: Point(275, 175)),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path("M275,175 v-150 a150,150 0 0,0 -150,150 L 275,175 z")
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(275 + 175j),
|
||||
// Line(275 + 175j, 275 + 25j),
|
||||
// Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j),
|
||||
// Line(125 + 175j, 275 + 175j),
|
||||
// Close(275 + 175j, 275 + 175j),
|
||||
// ),
|
||||
// )
|
||||
path1 = parsePath("M275,175 v-150 a150,150 0 0,0 -150,150 L 275,175 z");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(275, 175)),
|
||||
Line(start: Point(275, 175), end: Point(275, 25)),
|
||||
Arc(
|
||||
start: Point(275, 25),
|
||||
radius: Point(150, 150),
|
||||
rotation: 0,
|
||||
arc: false,
|
||||
sweep: false,
|
||||
end: Point(125, 175),
|
||||
),
|
||||
Line(start: Point(125, 175), end: Point(275, 175)),
|
||||
Close(start: Point(275, 175), end: Point(275, 175)),
|
||||
]),
|
||||
);
|
||||
|
||||
// path1 = parse_path(
|
||||
// """M600,350 l 50,-25
|
||||
// a25,25 -30 0,1 50,-25 l 50,-25
|
||||
// a25,50 -30 0,1 50,-25 l 50,-25
|
||||
// a25,75 -30 0,1 50,-25 l 50,-25
|
||||
// a25,100 -30 0,1 50,-25 l 50,-25"""
|
||||
// )
|
||||
// self.assertEqual(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(600 + 350j),
|
||||
// Line(600 + 350j, 650 + 325j),
|
||||
// Arc(650 + 325j, 25 + 25j, -30, 0, 1, 700 + 300j),
|
||||
// Line(700 + 300j, 750 + 275j),
|
||||
// Arc(750 + 275j, 25 + 50j, -30, 0, 1, 800 + 250j),
|
||||
// Line(800 + 250j, 850 + 225j),
|
||||
// Arc(850 + 225j, 25 + 75j, -30, 0, 1, 900 + 200j),
|
||||
// Line(900 + 200j, 950 + 175j),
|
||||
// Arc(950 + 175j, 25 + 100j, -30, 0, 1, 1000 + 150j),
|
||||
// Line(1000 + 150j, 1050 + 125j),
|
||||
// ),
|
||||
// );
|
||||
path1 = parsePath("""M600,350 l 50,-25
|
||||
a25,25 -30 0,1 50,-25 l 50,-25
|
||||
a25,50 -30 0,1 50,-25 l 50,-25
|
||||
a25,75 -30 0,1 50,-25 l 50,-25
|
||||
a25,100 -30 0,1 50,-25 l 50,-25""");
|
||||
expect(
|
||||
path1,
|
||||
Path.fromSegments(const [
|
||||
Move(to: Point(600, 350)),
|
||||
Line(start: Point(600, 350), end: Point(650, 325)),
|
||||
Arc(
|
||||
start: Point(650, 325),
|
||||
radius: Point(25, 25),
|
||||
rotation: -30,
|
||||
arc: false,
|
||||
sweep: true,
|
||||
end: Point(700, 300),
|
||||
),
|
||||
Line(start: Point(700, 300), end: Point(750, 275)),
|
||||
Arc(
|
||||
start: Point(750, 275),
|
||||
radius: Point(25, 50),
|
||||
rotation: -30,
|
||||
arc: false,
|
||||
sweep: true,
|
||||
end: Point(800, 250),
|
||||
),
|
||||
Line(start: Point(800, 250), end: Point(850, 225)),
|
||||
Arc(
|
||||
start: Point(850, 225),
|
||||
radius: Point(25, 75),
|
||||
rotation: -30,
|
||||
arc: false,
|
||||
sweep: true,
|
||||
end: Point(900, 200),
|
||||
),
|
||||
Line(start: Point(900, 200), end: Point(950, 175)),
|
||||
Arc(
|
||||
start: Point(950, 175),
|
||||
radius: Point(25, 100),
|
||||
rotation: -30,
|
||||
arc: false,
|
||||
sweep: true,
|
||||
end: Point(1000, 150),
|
||||
),
|
||||
Line(start: Point(1000, 150), end: Point(1050, 125)),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
// def test_others(self):
|
||||
// # Other paths that need testing:
|
||||
|
||||
// # Relative moveto:
|
||||
// path1 = parse_path("M 0 0 L 50 20 m 50 80 L 300 100 L 200 300 z")
|
||||
// self.assertEqual(
|
||||
// path1 = parsePath("M 0 0 L 50 20 m 50 80 L 300 100 L 200 300 z")
|
||||
// expect(
|
||||
// path1,
|
||||
// Path(
|
||||
// Path.fromSegments(const [
|
||||
// Move(0j),
|
||||
// Line(0 + 0j, 50 + 20j),
|
||||
// Move(100 + 100j),
|
||||
// Line(100 + 100j, 300 + 100j),
|
||||
// Line(300 + 100j, 200 + 300j),
|
||||
// Close(200 + 300j, 100 + 100j),
|
||||
// Line(start: Point(0, 0), end: Point(50, 20)),
|
||||
// Move(to: Point(100, 100)),
|
||||
// Line(start: Point(100, 100), end: Point(300, 100)),
|
||||
// Line(start: Point(300, 100), end: Point(200, 300)),
|
||||
// Close(Point(200, 300), Point(100, 100)),
|
||||
// ),
|
||||
// )
|
||||
|
||||
// # Initial smooth and relative CubicBezier
|
||||
// path1 = parse_path("""M100,200 s 150,-100 150,0""")
|
||||
// self.assertEqual(
|
||||
// path1 = parsePath("""M100,200 s 150,-100 150,0""")
|
||||
// expect(
|
||||
// path1,
|
||||
// Path(
|
||||
// Move(100 + 200j),
|
||||
// CubicBezier(100 + 200j, 100 + 200j, 250 + 100j, 250 + 200j),
|
||||
// Path.fromSegments(const [
|
||||
// Move(to: Point(100, 200)),
|
||||
// CubicBezier(start: Point(100, 200), control1: Point(100, 200), control2: Point(250, 100), end: Point(250, 200),),
|
||||
// ),
|
||||
// )
|
||||
|
||||
// # Initial smooth and relative QuadraticBezier
|
||||
// path1 = parse_path("""M100,200 t 150,0""")
|
||||
// self.assertEqual(
|
||||
// path1 = parsePath("""M100,200 t 150,0""")
|
||||
// expect(
|
||||
// path1,
|
||||
// Path(Move(100 + 200j), QuadraticBezier(100 + 200j, 100 + 200j, 250 + 200j)),
|
||||
// Path.fromSegments(const [Move(Point(100, 200)), QuadraticBezier(start: Point(100, 200), control: Point(100, 200), end: Point(250, 200)),),
|
||||
// )
|
||||
|
||||
// # Relative QuadraticBezier
|
||||
// path1 = parse_path("""M100,200 q 0,0 150,0""")
|
||||
// self.assertEqual(
|
||||
// path1 = parsePath("""M100,200 q 0,0 150,0""")
|
||||
// expect(
|
||||
// path1,
|
||||
// Path(Move(100 + 200j), QuadraticBezier(100 + 200j, 100 + 200j, 250 + 200j)),
|
||||
// Path.fromSegments(const [Move(Point(100, 200)), QuadraticBezier(start: Point(100, 200), control: Point(100, 200), end: Point(250, 200)),),
|
||||
// )
|
||||
|
||||
// def test_negative(self):
|
||||
// """You don't need spaces before a minus-sign"""
|
||||
// path1 = parse_path("M100,200c10-5,20-10,30-20")
|
||||
// path2 = parse_path("M 100 200 c 10 -5 20 -10 30 -20")
|
||||
// self.assertEqual(path1, path2)
|
||||
// path1 = parsePath("M100,200c10-5,20-10,30-20")
|
||||
// path2 = parsePath("M 100 200 c 10 -5 20 -10 30 -20")
|
||||
// expect(path1, path2)
|
||||
|
||||
// def test_numbers(self):
|
||||
// """Exponents and other number format cases"""
|
||||
// # It can be e or E, the plus is optional, and a minimum of +/-3.4e38 must be supported.
|
||||
// path1 = parse_path("M-3.4e38 3.4E+38L-3.4E-38,3.4e-38")
|
||||
// path2 = Path(
|
||||
// path1 = parsePath("M-3.4e38 3.4E+38L-3.4E-38,3.4e-38")
|
||||
// path2 = Path.fromSegments(const [
|
||||
// Move(-3.4e38 + 3.4e38j), Line(-3.4e38 + 3.4e38j, -3.4e-38 + 3.4e-38j)
|
||||
// )
|
||||
// self.assertEqual(path1, path2)
|
||||
// expect(path1, path2)
|
||||
|
||||
// def test_errors(self):
|
||||
// self.assertRaises(ValueError, parse_path, "M 100 100 L 200 200 Z 100 200")
|
||||
// self.assertRaises(ValueError, parsePath, "M 100 100 L 200 200 Z 100 200")
|
||||
|
||||
// def test_non_path(self):
|
||||
// # It's possible in SVG to create paths that has zero length,
|
||||
// # we need to handle that.
|
||||
|
||||
// path = parse_path("M10.236,100.184")
|
||||
// self.assertEqual(path.d(), "M 10.236,100.184")
|
||||
// path = parsePath("M10.236,100.184")
|
||||
// expect(path.d(), "M 10.236,100.184")
|
||||
|
||||
// def test_issue_45(self):
|
||||
// path = parse_path(
|
||||
// path = parsePath(
|
||||
// "m 1672.2372,-54.8161 "
|
||||
// "a 14.5445,14.5445 0 0 0 -11.3152,23.6652 "
|
||||
// "l 27.2573,27.2572 27.2572,-27.2572 "
|
||||
|
Reference in New Issue
Block a user