From c83821fa381d79a44e4516023df3f4cd8f0cab21 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 4 Aug 2025 21:11:37 +0200 Subject: [PATCH] treewide: dart format + analyze + some other fixes --- lib/common/point.dart | 9 +- lib/kanimaji.dart | 2 +- lib/kanimaji/animate_kanji.dart | 183 ++--- lib/kanimaji/bezier_cubic.dart | 10 +- lib/svg/parser.dart | 11 +- lib/svg/path.dart | 101 ++- lib/widgets/kanjimaji.dart | 9 +- test/svg/parser_test.dart | 76 +- test/svg/path_test.dart | 1254 +++++++++++++++---------------- test/svg/tokenizer_test.dart | 52 +- 10 files changed, 863 insertions(+), 844 deletions(-) diff --git a/lib/common/point.dart b/lib/common/point.dart index ab16dbc..0e30997 100644 --- a/lib/common/point.dart +++ b/lib/common/point.dart @@ -8,10 +8,11 @@ class Point { const Point.from({this.x = 0, this.y = 0}); static const zero = Point(0, 0); - operator +(covariant Point p) => Point(x + p.x, y + p.y); - operator -(covariant Point p) => Point(x - p.x, y - p.y); - operator *(covariant Point p) => Point(x * p.x, y * p.y); - operator /(covariant Point p) => Point(x / p.x, y / p.y); + Point operator +(covariant Point p) => Point(x + p.x, y + p.y); + Point operator -(covariant Point p) => Point(x - p.x, y - p.y); + Point operator *(covariant Point p) => Point(x * p.x, y * p.y); + Point operator /(covariant Point p) => Point(x / p.x, y / p.y); + Point operator -() => Point(-x, -y); @override bool operator ==(Object other) => diff --git a/lib/kanimaji.dart b/lib/kanimaji.dart index a5c46c0..190bacf 100644 --- a/lib/kanimaji.dart +++ b/lib/kanimaji.dart @@ -1,4 +1,4 @@ -library kanimaji; +library; /// A Calculator. class Calculator { diff --git a/lib/kanimaji/animate_kanji.dart b/lib/kanimaji/animate_kanji.dart index 8e3ece9..8364b3e 100644 --- a/lib/kanimaji/animate_kanji.dart +++ b/lib/kanimaji/animate_kanji.dart @@ -6,21 +6,19 @@ import '../common/point.dart'; import 'bezier_cubic.dart' as bezier_cubic; import 'package:xml/xml.dart'; -import 'package:path/path.dart'; double _computePathLength(String path) => parsePath(path).size(error: 1e-8).toDouble(); -String _shescape(String path) => - "'${path.replaceAll(RegExp(r"(?=['\\\\])"), "\\\\")}'"; +// String _shescape(String path) => +// "'${path.replaceAll(RegExp(r"(?=['\\\\])"), "\\\\")}'"; extension _Dedent on String { String get dedented { - final withoutEmptyLines = - this.split('\n').where((l) => l.isNotEmpty).toList(); + final withoutEmptyLines = split('\n').where((l) => l.isNotEmpty).toList(); final whitespaceAmounts = [ for (final line in withoutEmptyLines) - line.split('').takeWhile((c) => c == ' ').length + line.split('').takeWhile((c) => c == ' ').length, ]; final whitespaceToRemove = whitespaceAmounts.reduce(min); return withoutEmptyLines @@ -63,40 +61,34 @@ const pt2 = Point(1, 1); // class { // } -enum TimingFunction { - linear, - ease, - easeIn, - easeInOut, - easeOut, -} +enum TimingFunction { linear, ease, easeIn, easeInOut, easeOut } extension Funcs on TimingFunction { double Function(double) get func => { - TimingFunction.linear: (double x) => x, - TimingFunction.ease: (double x) => - bezier_cubic.value(pt1, easeCt1, easeCt2, pt2, x), - TimingFunction.easeIn: (double x) => - bezier_cubic.value(pt1, easeInCt1, easeInCt2, pt2, x), - TimingFunction.easeInOut: (double x) => - bezier_cubic.value(pt1, easeInOutCt1, easeInOutCt2, pt2, x), - TimingFunction.easeOut: (double x) => - bezier_cubic.value(pt1, easeOutCt1, easeOutCt2, pt2, x), - }[this]!; + TimingFunction.linear: (double x) => x, + TimingFunction.ease: (double x) => + bezier_cubic.value(pt1, easeCt1, easeCt2, pt2, x), + TimingFunction.easeIn: (double x) => + bezier_cubic.value(pt1, easeInCt1, easeInCt2, pt2, x), + TimingFunction.easeInOut: (double x) => + bezier_cubic.value(pt1, easeInOutCt1, easeInOutCt2, pt2, x), + TimingFunction.easeOut: (double x) => + bezier_cubic.value(pt1, easeOutCt1, easeOutCt2, pt2, x), + }[this]!; String get name => { - TimingFunction.linear: 'linear', - TimingFunction.ease: 'ease', - TimingFunction.easeIn: 'ease-in', - TimingFunction.easeInOut: 'ease-in-out', - TimingFunction.easeOut: 'ease-out', - }[this]!; + TimingFunction.linear: 'linear', + TimingFunction.ease: 'ease', + TimingFunction.easeIn: 'ease-in', + TimingFunction.easeInOut: 'ease-in-out', + TimingFunction.easeOut: 'ease-out', + }[this]!; } // we will need this to deal with svg const namespaces = { 'n': 'http://www.w3.org/2000/svg', - 'xlink': 'http://www.w3.org/1999/xlink' + 'xlink': 'http://www.w3.org/1999/xlink', }; // etree.register_namespace("xlink","http://www.w3.org/1999/xlink") // final parser = etree.XMLParser(remove_blank_text=true); @@ -124,26 +116,36 @@ double timeRescale(interval) => pow(2 * interval, 2.0 / 3).toDouble(); /// clear all extra elements this program may have previously added void clearPreviousElements(XmlDocument doc) { - for (final XmlNode el in doc - .getElement('svg', namespace: namespaces['n']) - ?.getElement('style', namespace: namespaces['n']) - ?.children ?? - []) { + for (final XmlNode el + in doc + .getElement('svg', namespace: namespaces['n']) + ?.getElement('style', namespace: namespaces['n']) + ?.children ?? + []) { if (RegExp(r'-Kanimaji$').hasMatch(el.getAttribute('id') ?? '')) { el.parent!.children.remove(el); } } - for (final XmlNode g in doc - .getElement('svg', namespace: namespaces['n']) - ?.getElement('g', namespace: namespaces['n']) - ?.children ?? - []) { + for (final XmlNode g + in doc + .getElement('svg', namespace: namespaces['n']) + ?.getElement('g', namespace: namespaces['n']) + ?.children ?? + []) { if (RegExp(r'-Kanimaji$').hasMatch(g.getAttribute('id') ?? '')) { g.parent!.children.remove(g); } } } +String basename(String path) { + final int lastSlash = path.lastIndexOf(Platform.pathSeparator); + if (lastSlash == -1) { + return path; + } + return path.substring(lastSlash + 1); +} + /// Note: setting any color to transparent will result in a much bigger /// filesize for GIFs. void createAnimation({ @@ -190,7 +192,8 @@ void createAnimation({ 'g', attributes: { 'id': 'kvg:$baseid-$id-Kanimaji', - 'style': 'fill:none;' + 'style': + 'fill:none;' 'stroke:$color;' 'stroke-width:$width;' 'stroke-linecap:round;' @@ -232,11 +235,12 @@ void createAnimation({ double tottime = 0; // for (final g in doc.xpath("/n:svg/n:g", namespaces=namespaces) { - for (final XmlNode g in doc - .getElement('svg', namespace: namespaces['n']) - ?.getElement('g', namespace: namespaces['n']) - ?.children ?? - []) { + for (final XmlNode g + in doc + .getElement('svg', namespace: namespaces['n']) + ?.getElement('g', namespace: namespaces['n']) + ?.children ?? + []) { if (RegExp(r'^kvg:StrokeNumbers_').hasMatch(g.getAttribute('id') ?? '')) { continue; } @@ -266,9 +270,7 @@ void createAnimation({ '\n/* CSS automatically generated by kanimaji.py, do not edit! */\n'; if (GENERATE_SVG) animatedCss = cssHeader; if (GENERATE_JS_SVG) { - jsAnimatedCss += cssHeader + - ''' - .backward {\n + jsAnimatedCss += '''$cssHeader .backward {\n animation-direction: reverse !important;\n } '''; @@ -287,18 +289,20 @@ void createAnimation({ double elapsedtime = 0; // add css elements for all strokes - for (final XmlNode g in doc - .getElement('svg', namespace: namespaces['n'])! - .findElements('g', namespace: namespaces['n'])) { + for (final XmlNode g + in doc + .getElement('svg', namespace: namespaces['n'])! + .findElements('g', namespace: namespaces['n'])) { // for (final g in doc.xpath("/n:svg/n:g", namespaces=namespaces)){ final groupid = g.getAttribute('id') ?? ''; if (RegExp(r'^kvg:StrokeNumbers_').hasMatch(groupid)) { - final String rule = ''' + final String rule = + ''' #${groupid.replaceAll(':', '\\3a ')} { display: none; } ''' - .dedented; + .dedented; if (GENERATE_SVG) animatedCss += rule; if (GENERATE_JS_SVG) jsAnimatedCss += rule; if (GENERATE_GIF) { @@ -310,13 +314,14 @@ void createAnimation({ } final gidcss = groupid.replaceAll(':', '\\3a '); - final rule = ''' + final rule = + ''' #$gidcss { stroke-width: ${strokeBorderWidth.toStringAsFixed(1)}px !important; stroke: $strokeBorderColor !important; } ''' - .dedented; + .dedented; if (GENERATE_SVG) animatedCss += rule; if (GENERATE_JS_SVG) jsAnimatedCss += rule; @@ -380,7 +385,8 @@ void createAnimation({ if (GENERATE_SVG) { // animation stroke progression - animatedCss += ''' + animatedCss += + ''' @keyframes strike-$pathname { 0% { stroke-dashoffset: ${pathlen.toStringAsFixed(3)}; } ${animStart.toStringAsFixed(3)}% { stroke-dashoffset: ${pathlen.toStringAsFixed(3)}; } @@ -398,11 +404,12 @@ void createAnimation({ showhide-$pathname ${animationTime.toStringAsFixed(3)}s step-start infinite; } ''' - .dedented; + .dedented; if (showBrush) { // brush element visibility - animatedCss += ''' + animatedCss += + ''' @keyframes showhide-brush-$pathname { ${animStart.toStringAsFixed(3)}% { visibility: hidden; } ${animEnd.toStringAsFixed(3)}% { visibility: visible; } @@ -414,7 +421,7 @@ void createAnimation({ showhide-brush-$pathname ${animationTime.toStringAsFixed(3)}s step-start infinite; } ''' - .dedented; + .dedented; } } @@ -423,17 +430,19 @@ void createAnimation({ // brush and background hidden by default if (showBrush) { - jsAnimatedCss += ''' + jsAnimatedCss += + ''' #$brushPathidcss, #$brushBorderPathidcss, #$bgPathidcss { visibility: hidden; } ''' - .dedented; + .dedented; } // hide stroke after current element const afterCurrent = '[class *= "current"]'; - jsAnimatedCss += ''' + jsAnimatedCss += + ''' $afterCurrent ~ #$animPathidcss { visibility: hidden; } @@ -451,9 +460,10 @@ void createAnimation({ animation: strike-$pathname ${relativeDuration.toStringAsFixed(3)}s ${timingFunction.name} forwards 1; } ''' - .dedented; + .dedented; if (showBrush) { - jsAnimatedCss += ''' + jsAnimatedCss += + ''' @keyframes strike-brush-$pathname { 0% { stroke-dashoffset: ${pathlen.toStringAsFixed(3)}; } 100% { stroke-dashoffset: 0.4; } @@ -464,7 +474,7 @@ void createAnimation({ animation: strike-brush-$pathname ${relativeDuration.toStringAsFixed(3)}s ${timingFunction.name} forwards 1; } ''' - .dedented; + .dedented; } } @@ -473,7 +483,7 @@ void createAnimation({ final time = k * GIF_FRAME_DURATION; final reltime = time * tottime / animationTime; // unscaled time - staticCss[k] = staticCss[k]! + '\n/* stroke $pathid */\n'; + staticCss[k] = '${staticCss[k]!}\n/* stroke $pathid */\n'; String rule = ''; @@ -486,7 +496,8 @@ void createAnimation({ rule += ", #$brushPathidcss, #$brushBorderPathidcss"; } - staticCss[k] = staticCss[k]! + + staticCss[k] = + staticCss[k]! + ''' %$rule { visibility: hidden; @@ -501,7 +512,8 @@ void createAnimation({ rule += ", #$brushPathidcss, #$brushBorderPathidcss"; } - staticCss[k] = staticCss[k]! + + staticCss[k] = + staticCss[k]! + ''' $rule { visibility: hidden; @@ -513,7 +525,8 @@ void createAnimation({ ((reltime - elapsedtime) / (newelapsedtime - elapsedtime)); final progression = timingFunction.func(intervalprop); - staticCss[k] = staticCss[k]! + + staticCss[k] = + staticCss[k]! + ''' #$animPathidcss { stroke-dasharray: ${pathlen.toStringAsFixed(3)} ${(pathlen + 0.002).toStringAsFixed(3)}; @@ -523,7 +536,8 @@ void createAnimation({ ''' .dedented; if (showBrush) { - staticCss[k] = staticCss[k]! + + staticCss[k] = + staticCss[k]! + ''' #$brushPathidcss, #$brushBorderPathidcss { stroke-dasharray: 0.001 ${(pathlen + 0.002).toStringAsFixed(3)}; @@ -554,13 +568,13 @@ void createAnimation({ if (GENERATE_SVG) { print(animatedCss); final builder = XmlBuilder(); - final style = (builder - ..element( - 'style', - attributes: {'id': "style-Kanimaji", 'type': 'text/css'}, - nest: animatedCss, - )) - .buildFragment(); + final style = + (builder..element( + 'style', + attributes: {'id': "style-Kanimaji", 'type': 'text/css'}, + nest: animatedCss, + )) + .buildFragment(); doc.root.firstElementChild!.children.insert(0, style); File(outputFile).writeAsStringSync(doc.toXmlString(pretty: true)); doc.root.children.removeAt(0); @@ -684,16 +698,15 @@ void main(List args) { final fileList = []; for (int k = 0; k < kanji.length; k++) { createAnimation( - inputFile: 'assets/kanjivg/kanji/${kanji.codeUnits[k].toRadixString(16).padLeft(5, '0')}.svg', - outputFile: '${k+1}.svg', - ); - fileList.add('${k+1}.svg'); + inputFile: + 'assets/kanjivg/kanji/${kanji.codeUnits[k].toRadixString(16).padLeft(5, '0')}.svg', + outputFile: '${k + 1}.svg', + ); + fileList.add('${k + 1}.svg'); } File('index.html').writeAsStringSync( - '' + - fileList.map((e) => File(e).readAsStringSync().replaceAll(']>', '')).join('\n') + - '' + '${fileList.map((e) => File(e).readAsStringSync().replaceAll(']>', '')).join('\n')}', ); // createAnimation( // inputFile: 'assets/kanjivg/kanji/060c5.svg', diff --git a/lib/kanimaji/bezier_cubic.dart b/lib/kanimaji/bezier_cubic.dart index 326023a..17dac50 100644 --- a/lib/kanimaji/bezier_cubic.dart +++ b/lib/kanimaji/bezier_cubic.dart @@ -1,7 +1,5 @@ - import 'dart:math' as math; - import '../common/point.dart'; // class Point { @@ -31,7 +29,8 @@ double time(Point pt1, Point ct1, Point ct2, Point pt2, double x) { final num c = 3 * ct2.x - 3 * pt2.x; final num d = pt2.x - x; - if (a.abs() < 0.000000001) { // quadratic + if (a.abs() < 0.000000001) { + // quadratic if (b.abs() < 0.000000001) return -d / c; // linear final qb = c / b; @@ -45,7 +44,8 @@ double time(Point pt1, Point ct1, Point ct2, Point pt2, double x) { final addcoef = -b / (3 * a); final lmbd = sq(q) / 4 + cb(p) / 27; - if (lmbd >= 0) { // real + if (lmbd >= 0) { + // real final sqlambda = sqrt(lmbd); final tmp = thrt(-q / 2 + (q < 0 ? sqlambda : -sqlambda)); return tmp - p / (3 * tmp) + addcoef; @@ -84,4 +84,4 @@ double value(Point pt1, Point ct1, Point ct2, Point pt2, double x) { // for i in range(0,part+1,1): // x = float(i) / part // y = value(pt1, ct1, ct2, pt2, x) -// f.write("%f %f\n" % (x,y)) \ No newline at end of file +// f.write("%f %f\n" % (x,y)) diff --git a/lib/svg/parser.dart b/lib/svg/parser.dart index f1e1e14..15a432e 100644 --- a/lib/svg/parser.dart +++ b/lib/svg/parser.dart @@ -1,6 +1,7 @@ /// SVG Path specification parser /// /// See https://pypi.org/project/svg.path/ for the original implementation. +library; import '../common/point.dart'; import 'path.dart'; @@ -25,7 +26,7 @@ const _commands = { 'T', 't', 'A', - 'a' + 'a', }; // const _uppercaseCommands = {'M', 'Z', 'L', 'H', 'V', 'C', 'S', 'Q', 'T', 'A'}; @@ -181,8 +182,9 @@ class Token { other is Token && command == other.command && args.length == other.args.length && - ![for (int i = 0; i < args.length; i++) args[i] == other.args[i]] - .any((b) => !b); + ![ + for (int i = 0; i < args.length; i++) args[i] == other.args[i], + ].any((b) => !b); @override int get hashCode => command.hashCode ^ args.hashCode; @@ -358,7 +360,8 @@ Path parsePath(String pathdef) { // The control point is assumed to be the reflection of // the control point on the previous command relative // to the current point. - control = currentPos + + control = + currentPos + currentPos - (segments.last as QuadraticBezier).control; } else { diff --git a/lib/svg/path.dart b/lib/svg/path.dart index 3718ff2..0714c06 100644 --- a/lib/svg/path.dart +++ b/lib/svg/path.dart @@ -1,5 +1,6 @@ /// This file contains classes for the different types of SVG path segments as /// well as a Path object that contains a sequence of path segments. +library; import 'dart:collection'; import 'dart:math' as math; @@ -69,10 +70,7 @@ abstract class SvgPath { final Point start; final Point end; - const SvgPath({ - required this.start, - required this.end, - }); + const SvgPath({required this.start, required this.end}); @override bool operator ==(Object other) => @@ -89,10 +87,7 @@ abstract class SvgPath { } abstract class Bezier extends SvgPath { - const Bezier({ - required Point start, - required Point end, - }) : super(start: start, end: end); + const Bezier({required super.start, required super.end}); @override bool operator ==(Object other) => other is Bezier && super == other; @@ -107,10 +102,7 @@ abstract class Bezier extends SvgPath { /// A straight line /// The base for Line() and Close(). class Linear extends SvgPath { - const Linear({ - required Point start, - required Point end, - }) : super(start: start, end: end); + const Linear({required super.start, required super.end}); @override bool operator ==(Object other) => other is Linear && super == other; @@ -129,10 +121,7 @@ class Linear extends SvgPath { } class Line extends Linear { - const Line({ - required Point start, - required Point end, - }) : super(start: start, end: end); + const Line({required super.start, required super.end}); @override bool operator ==(Object other) => other is Line && super == other; @@ -151,11 +140,11 @@ class CubicBezier extends Bezier { final Point control2; const CubicBezier({ - required Point start, + required super.start, required this.control1, required this.control2, - required Point end, - }) : super(start: start, end: end); + required super.end, + }); @override bool operator ==(Object other) => @@ -168,13 +157,14 @@ class CubicBezier extends Bezier { int get hashCode => super.hashCode ^ control1.hashCode ^ control2.hashCode; @override - String toString() => "CubicBezier(start=$start, control1=$control1, " + String toString() => + "CubicBezier(start=$start, control1=$control1, " "control2=$control2, end=$end)"; @override bool isSmoothFrom(Object? previous) => previous is CubicBezier ? start == previous.end && - control1 - start == previous.end - previous.control2 + control1 - start == previous.end - previous.control2 : control1 == start; @override @@ -205,10 +195,10 @@ class QuadraticBezier extends Bezier { final Point control; const QuadraticBezier({ - required Point start, - required Point end, + required super.start, + required super.end, required this.control, - }) : super(start: start, end: end); + }); @override bool operator ==(Object other) => @@ -224,7 +214,7 @@ class QuadraticBezier extends Bezier { @override bool isSmoothFrom(Object? previous) => previous is QuadraticBezier ? start == previous.end && - (control - start) == (previous.end - previous.control) + (control - start) == (previous.end - previous.control) : control == start; @override @@ -258,7 +248,8 @@ class QuadraticBezier extends Bezier { final num c2 = 2 * sqrt(C); final num bA = B / a2; - s = (a32 * sabc + + s = + (a32 * sabc + a2 * B * (sabc - c2) + (4 * C * A - (B * B)) * log((2 * a2 + bA + sabc) / (bA + c2))) / (4 * a32); @@ -280,13 +271,13 @@ class Arc extends SvgPath { // late num delta; const Arc({ - required Point start, - required Point end, + required super.start, + required super.end, required this.radius, required this.rotation, required this.arc, required this.sweep, - }) : super(start: start, end: end); + }); @override bool operator ==(Object other) => @@ -306,10 +297,10 @@ class Arc extends SvgPath { sweep.hashCode; @override - String toString() => 'Arc(start=$start, radius=$radius, rotation=$rotation, ' + 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 num get _cosr => cos(radians(rotation)); @@ -337,16 +328,17 @@ class Arc extends SvgPath { num get _cyprim => -c * _ry * _x1prim / _rx; num get radiusScale { - final rs = (_x1primSq / (radius.x * radius.x)) + + final rs = + (_x1primSq / (radius.x * radius.x)) + (_y1primSq / (radius.y * radius.y)); return rs > 1 ? sqrt(rs) : 1; } Point get center => Point( - (_cosr * _cxprim - _sinr * _cyprim) + ((start.x + end.x) / 2), - (_sinr * _cxprim + _cosr * _cyprim) + ((start.y + end.y) / 2), - ); - + (_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; @@ -365,7 +357,8 @@ class Arc extends SvgPath { d = -1.0; } - return ((((_ux * _vy - _uy * _vx) < 0) ? -1 : 1) * degrees(acos(d))) % 360 - (!sweep ? 360 : 0); + return ((((_ux * _vy - _uy * _vx) < 0) ? -1 : 1) * degrees(acos(d))) % 360 - + (!sweep ? 360 : 0); } @override @@ -375,7 +368,7 @@ class Arc extends SvgPath { // This should be treated as a straight line if (this.radius.x == 0 || this.radius.y == 0) { - return start + (end - start) * pos; + return start + (end - start).times(pos); } final angle = radians(theta + pos * delta); @@ -415,14 +408,15 @@ class Arc extends SvgPath { final startPoint = point(0); final endPoint = point(1); return segmentLength( - curve: this, - start: 0, - end: 1, - startPoint: startPoint, - endPoint: endPoint, - error: error, - minDepth: minDepth, - depth: 0); + curve: this, + start: 0, + end: 1, + startPoint: startPoint, + endPoint: endPoint, + error: error, + minDepth: minDepth, + depth: 0, + ); } } @@ -449,10 +443,7 @@ class Move extends SvgPath { /// Represents the closepath command class Close extends Linear { - const Close({ - required Point start, - required Point end, - }) : super(start: start, end: end); + const Close({required super.start, required super.end}); @override bool operator ==(Object other) => other is Close && super == other; @@ -502,12 +493,14 @@ class Path extends ListBase { String toString() => 'Path(${[for (final s in segments) s.toString()].join(", ")})'; - void _calcLengths( - {num error = defaultError, int minDepth = defaultMinDepth}) { + void _calcLengths({ + num error = defaultError, + int minDepth = defaultMinDepth, + }) { if (_memoizedLength != null) return; final lengths = [ - for (final s in segments) s!.size(error: error, minDepth: minDepth) + for (final s in segments) s!.size(error: error, minDepth: minDepth), ]; _memoizedLength = lengths.reduce((a, b) => a + b); if (_memoizedLength == 0) { @@ -552,7 +545,7 @@ class Path extends ListBase { return segments[i]!.point(segmentPos); } - num size({error = defaultError, minDepth = defaultMinDepth}) { + num size({double error = defaultError, int minDepth = defaultMinDepth}) { _calcLengths(error: error, minDepth: minDepth); return _memoizedLength!; } diff --git a/lib/widgets/kanjimaji.dart b/lib/widgets/kanjimaji.dart index f880fa3..88e1c3d 100644 --- a/lib/widgets/kanjimaji.dart +++ b/lib/widgets/kanjimaji.dart @@ -1,15 +1,8 @@ import 'package:flutter/material.dart'; -extension _Hexcode on Color { - String get hexcode => '#${value.toRadixString(16).padLeft(8, '0')}'; -} - class Kanimaji extends StatelessWidget { final String kanji; - const Kanimaji({ - Key? key, - required this.kanji, - }) : super(key: key); + const Kanimaji({super.key, required this.kanji}); @override Widget build(BuildContext context) { diff --git a/test/svg/parser_test.dart b/test/svg/parser_test.dart index b1b527c..2aa115c 100644 --- a/test/svg/parser_test.dart +++ b/test/svg/parser_test.dart @@ -6,16 +6,17 @@ import 'package:kanimaji/svg/path.dart'; void main() { group("Examples from the SVG spec", () { test( - "[Path 1]: MLLz", - () => expect( - parsePath("M 100 100 L 300 100 L 200 300 z"), - Path.fromSegments(const [ - Move(to: Point(100, 100)), - Line(start: Point(100, 100), end: Point(300, 100)), - Line(start: Point(300, 100), end: Point(200, 300)), - Close(start: Point(200, 300), end: Point(100, 100)), - ]), - )); + "[Path 1]: MLLz", + () => expect( + parsePath("M 100 100 L 300 100 L 200 300 z"), + Path.fromSegments(const [ + Move(to: Point(100, 100)), + Line(start: Point(100, 100), end: Point(300, 100)), + Line(start: Point(300, 100), end: Point(200, 300)), + Close(start: Point(200, 300), end: Point(100, 100)), + ]), + ), + ); // test( @@ -160,10 +161,11 @@ void main() { 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)), + 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), @@ -347,9 +349,10 @@ void main() { Path.fromSegments(const [ Move(to: Point(100, 200)), QuadraticBezier( - start: Point(100, 200), - control: Point(100, 200), - end: Point(250, 200)), + start: Point(100, 200), + control: Point(100, 200), + end: Point(250, 200), + ), ]), ), ); @@ -361,9 +364,10 @@ void main() { Path.fromSegments(const [ Move(to: Point(100, 200)), QuadraticBezier( - start: Point(100, 200), - control: Point(100, 200), - end: Point(250, 200)), + start: Point(100, 200), + control: Point(100, 200), + end: Point(250, 200), + ), ]), ), ); @@ -382,12 +386,12 @@ void main() { () => // It can be e or E, the plus is optional, and a minimum of +/-3.4e38 must be supported. expect( - parsePath("M-3.4e38 3.4E+38L-3.4E-38,3.4e-38"), - Path.fromSegments(const [ - Move(to: Point(-3.4e38, 3.4e38)), - Line(start: Point(-3.4e38, 3.4e38), end: Point(-3.4e-38, 3.4e-38)) - ]), - ), + parsePath("M-3.4e38 3.4E+38L-3.4E-38,3.4e-38"), + Path.fromSegments(const [ + Move(to: Point(-3.4e38, 3.4e38)), + Line(start: Point(-3.4e38, 3.4e38), end: Point(-3.4e-38, 3.4e-38)), + ]), + ), ); test( @@ -405,15 +409,17 @@ void main() { ); test('svg.path library, issue 45', () { - final 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 " - "a 14.5445,14.5445 0 0 0 -11.3012,-23.634 " - "a 14.5445,14.5445 0 0 0 -11.414,5.4625 " - "l -4.542,4.5420 " - "l -4.5437,-4.5420 " - "a 14.5445,14.5445 0 0 0 -11.3984,-5.4937 " - "z"); + final 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 " + "a 14.5445,14.5445 0 0 0 -11.3012,-23.634 " + "a 14.5445,14.5445 0 0 0 -11.414,5.4625 " + "l -4.542,4.5420 " + "l -4.5437,-4.5420 " + "a 14.5445,14.5445 0 0 0 -11.3984,-5.4937 " + "z", + ); expect(path.d(), contains("A 14.5445,14.5445 0 0,0 1672.2372,-54.8161 Z")); }); } diff --git a/test/svg/path_test.dart b/test/svg/path_test.dart index cb56a23..a5bb843 100644 --- a/test/svg/path_test.dart +++ b/test/svg/path_test.dart @@ -5,7 +5,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:kanimaji/common/point.dart'; import 'package:kanimaji/svg/path.dart'; - // from ..path import CubicBezier, QuadraticBezier, Line, Arc, Move, Close, Path // Most of these test points are not calculated serparately, as that would @@ -41,636 +40,631 @@ import 'package:kanimaji/svg/path.dart'; // featureValueOf(actual) => (actual as Point).x; // } -class MoreOrLessEqualsToPoint extends Matcher { - const MoreOrLessEqualsToPoint(); +// class MoreOrLessEqualsToPoint extends Matcher { +// const MoreOrLessEqualsToPoint(); - @override - bool matches(covariant Finder finder, Map matchState) - => finder is Point && finder.x +// @override +// bool matches(covariant Finder finder, Map matchState) +// => finder is Point && matchState['' - @override - Description describe(Description description) => description.add('in card'); -} +// @override +// Description describe(Description description) => description.add('in card'); +// } void main() { - group('Line tests', () { - -test('Test lines', () { - - // These points are calculated, and not just regression tests. - const line1 = Line(start:Point.zero, end:Point(400, 0)); - expect(line1.point(0), moreOrLessEquals(0)); - // expect(line1.point(0.3), moreOrLessEquals(const Point(120, 0))); - // expect(line1.point(0.5), moreOrLessEquals(const Point(200, 0))); - // expect(line1.point(0.9), moreOrLessEquals(const Point(360, 0))); - // expect(line1.point(1), moreOrLessEquals(const Point(400, 0))); - expect(line1.size(), moreOrLessEquals(400)); - - const line2 = Line(start: Point(400, 0), end:Point(400, 300)); - // expect(line2.point(0), (400 + 0j)) - // expect(line2.point(0.3), (400 + 90j)) - // expect(line2.point(0.5), (400 + 150j)) - // expect(line2.point(0.9), (400 + 270j)) - // expect(line2.point(1), (400 + 300j)) - expect(line2.size(), moreOrLessEquals(300)); - - const line3 = Line(start:Point(400, 300), end:Point.zero); - // expect(line3.point(0), (400 + 300j)) - // expect(line3.point(0.3), (280 + 210j)) - // expect(line3.point(0.5), (200 + 150j)) - // expect(line3.point(0.9), (40 + 30j)) - // expect(line3.point(1), (0j)) - expect(line3.size(), moreOrLessEquals(500)); -}); - - def test_equality(self): - // This is to test the __eq__ and __ne__ methods, so we can't use - // assertEqual and assertNotEqual - line = Line(0j, 400 + 0j) - self.assertTrue(line == Line(0, 400)) - self.assertTrue(line != Line(100, 400)) - self.assertFalse(line == str(line)) - self.assertTrue(line != str(line)) - self.assertFalse( - CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) == line - ) - - }); - - - -// class CubicBezierTest(unittest.TestCase): -// def test_approx_circle(self): -// """This is a approximate circle drawn in Inkscape""" - -// arc1 = CubicBezier( -// complex(0, 0), -// complex(0, 109.66797), -// complex(-88.90345, 198.57142), -// complex(-198.57142, 198.57142), -// ) - -// self.assertAlmostEqual(arc1.point(0), (0j)) -// self.assertAlmostEqual(arc1.point(0.1), (-2.59896457 + 32.20931647j)) -// self.assertAlmostEqual(arc1.point(0.2), (-10.12330256 + 62.76392816j)) -// self.assertAlmostEqual(arc1.point(0.3), (-22.16418039 + 91.25500149j)) -// self.assertAlmostEqual(arc1.point(0.4), (-38.31276448 + 117.27370288j)) -// self.assertAlmostEqual(arc1.point(0.5), (-58.16022125 + 140.41119875j)) -// self.assertAlmostEqual(arc1.point(0.6), (-81.29771712 + 160.25865552j)) -// self.assertAlmostEqual(arc1.point(0.7), (-107.31641851 + 176.40723961j)) -// self.assertAlmostEqual(arc1.point(0.8), (-135.80749184 + 188.44811744j)) -// self.assertAlmostEqual(arc1.point(0.9), (-166.36210353 + 195.97245543j)) -// self.assertAlmostEqual(arc1.point(1), (-198.57142 + 198.57142j)) - -// arc2 = CubicBezier( -// complex(-198.57142, 198.57142), -// complex(-109.66797 - 198.57142, 0 + 198.57142), -// complex(-198.57143 - 198.57142, -88.90345 + 198.57142), -// complex(-198.57143 - 198.57142, 0), -// ) - -// self.assertAlmostEqual(arc2.point(0), (-198.57142 + 198.57142j)) -// self.assertAlmostEqual(arc2.point(0.1), (-230.78073675 + 195.97245543j)) -// self.assertAlmostEqual(arc2.point(0.2), (-261.3353492 + 188.44811744j)) -// self.assertAlmostEqual(arc2.point(0.3), (-289.82642365 + 176.40723961j)) -// self.assertAlmostEqual(arc2.point(0.4), (-315.8451264 + 160.25865552j)) -// self.assertAlmostEqual(arc2.point(0.5), (-338.98262375 + 140.41119875j)) -// self.assertAlmostEqual(arc2.point(0.6), (-358.830082 + 117.27370288j)) -// self.assertAlmostEqual(arc2.point(0.7), (-374.97866745 + 91.25500149j)) -// self.assertAlmostEqual(arc2.point(0.8), (-387.0195464 + 62.76392816j)) -// self.assertAlmostEqual(arc2.point(0.9), (-394.54388515 + 32.20931647j)) -// self.assertAlmostEqual(arc2.point(1), (-397.14285 + 0j)) - -// arc3 = CubicBezier( -// complex(-198.57143 - 198.57142, 0), -// complex(0 - 198.57143 - 198.57142, -109.66797), -// complex(88.90346 - 198.57143 - 198.57142, -198.57143), -// complex(-198.57142, -198.57143), -// ) - -// self.assertAlmostEqual(arc3.point(0), (-397.14285 + 0j)) -// self.assertAlmostEqual(arc3.point(0.1), (-394.54388515 - 32.20931675j)) -// self.assertAlmostEqual(arc3.point(0.2), (-387.0195464 - 62.7639292j)) -// self.assertAlmostEqual(arc3.point(0.3), (-374.97866745 - 91.25500365j)) -// self.assertAlmostEqual(arc3.point(0.4), (-358.830082 - 117.2737064j)) -// self.assertAlmostEqual(arc3.point(0.5), (-338.98262375 - 140.41120375j)) -// self.assertAlmostEqual(arc3.point(0.6), (-315.8451264 - 160.258662j)) -// self.assertAlmostEqual(arc3.point(0.7), (-289.82642365 - 176.40724745j)) -// self.assertAlmostEqual(arc3.point(0.8), (-261.3353492 - 188.4481264j)) -// self.assertAlmostEqual(arc3.point(0.9), (-230.78073675 - 195.97246515j)) -// self.assertAlmostEqual(arc3.point(1), (-198.57142 - 198.57143j)) - -// arc4 = CubicBezier( -// complex(-198.57142, -198.57143), -// complex(109.66797 - 198.57142, 0 - 198.57143), -// complex(0, 88.90346 - 198.57143), -// complex(0, 0), -// ) - -// self.assertAlmostEqual(arc4.point(0), (-198.57142 - 198.57143j)) -// self.assertAlmostEqual(arc4.point(0.1), (-166.36210353 - 195.97246515j)) -// self.assertAlmostEqual(arc4.point(0.2), (-135.80749184 - 188.4481264j)) -// self.assertAlmostEqual(arc4.point(0.3), (-107.31641851 - 176.40724745j)) -// self.assertAlmostEqual(arc4.point(0.4), (-81.29771712 - 160.258662j)) -// self.assertAlmostEqual(arc4.point(0.5), (-58.16022125 - 140.41120375j)) -// self.assertAlmostEqual(arc4.point(0.6), (-38.31276448 - 117.2737064j)) -// self.assertAlmostEqual(arc4.point(0.7), (-22.16418039 - 91.25500365j)) -// self.assertAlmostEqual(arc4.point(0.8), (-10.12330256 - 62.7639292j)) -// self.assertAlmostEqual(arc4.point(0.9), (-2.59896457 - 32.20931675j)) -// self.assertAlmostEqual(arc4.point(1), (0j)) - -// def test_svg_examples(self): - -// # M100,200 C100,100 250,100 250,200 -// path1 = CubicBezier(100 + 200j, 100 + 100j, 250 + 100j, 250 + 200j) -// self.assertAlmostEqual(path1.point(0), (100 + 200j)) -// self.assertAlmostEqual(path1.point(0.3), (132.4 + 137j)) -// self.assertAlmostEqual(path1.point(0.5), (175 + 125j)) -// self.assertAlmostEqual(path1.point(0.9), (245.8 + 173j)) -// self.assertAlmostEqual(path1.point(1), (250 + 200j)) - -// # S400,300 400,200 -// path2 = CubicBezier(250 + 200j, 250 + 300j, 400 + 300j, 400 + 200j) -// self.assertAlmostEqual(path2.point(0), (250 + 200j)) -// self.assertAlmostEqual(path2.point(0.3), (282.4 + 263j)) -// self.assertAlmostEqual(path2.point(0.5), (325 + 275j)) -// self.assertAlmostEqual(path2.point(0.9), (395.8 + 227j)) -// self.assertAlmostEqual(path2.point(1), (400 + 200j)) - -// # M100,200 C100,100 400,100 400,200 -// path3 = CubicBezier(100 + 200j, 100 + 100j, 400 + 100j, 400 + 200j) -// self.assertAlmostEqual(path3.point(0), (100 + 200j)) -// self.assertAlmostEqual(path3.point(0.3), (164.8 + 137j)) -// self.assertAlmostEqual(path3.point(0.5), (250 + 125j)) -// self.assertAlmostEqual(path3.point(0.9), (391.6 + 173j)) -// self.assertAlmostEqual(path3.point(1), (400 + 200j)) - -// # M100,500 C25,400 475,400 400,500 -// path4 = CubicBezier(100 + 500j, 25 + 400j, 475 + 400j, 400 + 500j) -// self.assertAlmostEqual(path4.point(0), (100 + 500j)) -// self.assertAlmostEqual(path4.point(0.3), (145.9 + 437j)) -// self.assertAlmostEqual(path4.point(0.5), (250 + 425j)) -// self.assertAlmostEqual(path4.point(0.9), (407.8 + 473j)) -// self.assertAlmostEqual(path4.point(1), (400 + 500j)) - -// # M100,800 C175,700 325,700 400,800 -// path5 = CubicBezier(100 + 800j, 175 + 700j, 325 + 700j, 400 + 800j) -// self.assertAlmostEqual(path5.point(0), (100 + 800j)) -// self.assertAlmostEqual(path5.point(0.3), (183.7 + 737j)) -// self.assertAlmostEqual(path5.point(0.5), (250 + 725j)) -// self.assertAlmostEqual(path5.point(0.9), (375.4 + 773j)) -// self.assertAlmostEqual(path5.point(1), (400 + 800j)) - -// # M600,200 C675,100 975,100 900,200 -// path6 = CubicBezier(600 + 200j, 675 + 100j, 975 + 100j, 900 + 200j) -// self.assertAlmostEqual(path6.point(0), (600 + 200j)) -// self.assertAlmostEqual(path6.point(0.3), (712.05 + 137j)) -// self.assertAlmostEqual(path6.point(0.5), (806.25 + 125j)) -// self.assertAlmostEqual(path6.point(0.9), (911.85 + 173j)) -// self.assertAlmostEqual(path6.point(1), (900 + 200j)) - -// # M600,500 C600,350 900,650 900,500 -// path7 = CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) -// self.assertAlmostEqual(path7.point(0), (600 + 500j)) -// self.assertAlmostEqual(path7.point(0.3), (664.8 + 462.2j)) -// self.assertAlmostEqual(path7.point(0.5), (750 + 500j)) -// self.assertAlmostEqual(path7.point(0.9), (891.6 + 532.4j)) -// self.assertAlmostEqual(path7.point(1), (900 + 500j)) - -// # M600,800 C625,700 725,700 750,800 -// path8 = CubicBezier(600 + 800j, 625 + 700j, 725 + 700j, 750 + 800j) -// self.assertAlmostEqual(path8.point(0), (600 + 800j)) -// self.assertAlmostEqual(path8.point(0.3), (638.7 + 737j)) -// self.assertAlmostEqual(path8.point(0.5), (675 + 725j)) -// self.assertAlmostEqual(path8.point(0.9), (740.4 + 773j)) -// self.assertAlmostEqual(path8.point(1), (750 + 800j)) - -// # S875,900 900,800 -// inversion = (750 + 800j) + (750 + 800j) - (725 + 700j) -// path9 = CubicBezier(750 + 800j, inversion, 875 + 900j, 900 + 800j) -// self.assertAlmostEqual(path9.point(0), (750 + 800j)) -// self.assertAlmostEqual(path9.point(0.3), (788.7 + 863j)) -// self.assertAlmostEqual(path9.point(0.5), (825 + 875j)) -// self.assertAlmostEqual(path9.point(0.9), (890.4 + 827j)) -// self.assertAlmostEqual(path9.point(1), (900 + 800j)) - -// def test_length(self): - -// # A straight line: -// arc = CubicBezier( -// complex(0, 0), complex(0, 0), complex(0, 100), complex(0, 100) -// ) - -// self.assertAlmostEqual(arc.length(), 100) - -// # A diagonal line: -// arc = CubicBezier( -// complex(0, 0), complex(0, 0), complex(100, 100), complex(100, 100) -// ) - -// self.assertAlmostEqual(arc.length(), sqrt(2 * 100 * 100)) - -// # A quarter circle arc with radius 100: -// kappa = ( -// 4 * (sqrt(2) - 1) / 3 -// ) # http://www.whizkidtech.redprince.net/bezier/circle/ - -// arc = CubicBezier( -// complex(0, 0), -// complex(0, kappa * 100), -// complex(100 - kappa * 100, 100), -// complex(100, 100), -// ) - -// # We can't compare with pi*50 here, because this is just an -// # approximation of a circle arc. pi*50 is 157.079632679 -// # So this is just yet another "warn if this changes" test. -// # This value is not verified to be correct. -// self.assertAlmostEqual(arc.length(), 157.1016698) - -// # A recursive solution has also been suggested, but for CubicBezier -// # curves it could get a false solution on curves where the midpoint is on a -// # straight line between the start and end. For example, the following -// # curve would get solved as a straight line and get the length 300. -// # Make sure this is not the case. -// arc = CubicBezier( -// complex(600, 500), complex(600, 350), complex(900, 650), complex(900, 500) -// ) -// self.assertTrue(arc.length() > 300.0) - -// def test_equality(self): -// # This is to test the __eq__ and __ne__ methods, so we can't use -// # assertEqual and assertNotEqual -// segment = CubicBezier( -// complex(600, 500), complex(600, 350), complex(900, 650), complex(900, 500) -// ) - -// self.assertTrue( -// segment == CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) -// ) -// self.assertTrue( -// segment != CubicBezier(600 + 501j, 600 + 350j, 900 + 650j, 900 + 500j) -// ) -// self.assertTrue(segment != Line(0, 400)) - - -// class QuadraticBezierTest(unittest.TestCase): -// def test_svg_examples(self): -// """These is the path in the SVG specs""" -// # M200,300 Q400,50 600,300 T1000,300 -// path1 = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) -// self.assertAlmostEqual(path1.point(0), (200 + 300j)) -// self.assertAlmostEqual(path1.point(0.3), (320 + 195j)) -// self.assertAlmostEqual(path1.point(0.5), (400 + 175j)) -// self.assertAlmostEqual(path1.point(0.9), (560 + 255j)) -// self.assertAlmostEqual(path1.point(1), (600 + 300j)) - -// # T1000, 300 -// inversion = (600 + 300j) + (600 + 300j) - (400 + 50j) -// path2 = QuadraticBezier(600 + 300j, inversion, 1000 + 300j) -// self.assertAlmostEqual(path2.point(0), (600 + 300j)) -// self.assertAlmostEqual(path2.point(0.3), (720 + 405j)) -// self.assertAlmostEqual(path2.point(0.5), (800 + 425j)) -// self.assertAlmostEqual(path2.point(0.9), (960 + 345j)) -// self.assertAlmostEqual(path2.point(1), (1000 + 300j)) - -// def test_length(self): -// # expected results calculated with -// # svg.path.segment_length(q, 0, 1, q.start, q.end, 1e-14, 20, 0) -// q1 = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) -// q2 = QuadraticBezier(200 + 300j, 400 + 50j, 500 + 200j) -// closedq = QuadraticBezier(6 + 2j, 5 - 1j, 6 + 2j) -// linq1 = QuadraticBezier(1, 2, 3) -// linq2 = QuadraticBezier(1 + 3j, 2 + 5j, -9 - 17j) -// nodalq = QuadraticBezier(1, 1, 1) -// tests = [ -// (q1, 487.77109389525975), -// (q2, 379.90458193489155), -// (closedq, 3.1622776601683795), -// (linq1, 2), -// (linq2, 22.73335777124786), -// (nodalq, 0), -// ] -// for q, exp_res in tests: -// self.assertAlmostEqual(q.length(), exp_res) - -// def test_equality(self): -// # This is to test the __eq__ and __ne__ methods, so we can't use -// # assertEqual and assertNotEqual -// segment = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) -// self.assertTrue(segment == QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j)) -// self.assertTrue(segment != QuadraticBezier(200 + 301j, 400 + 50j, 600 + 300j)) -// self.assertFalse(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j)) -// self.assertTrue(Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) != segment) - - -// class ArcTest(unittest.TestCase): -// def test_points(self): -// arc1 = Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) -// self.assertAlmostEqual(arc1.center, 100 + 0j) -// self.assertAlmostEqual(arc1.theta, 180.0) -// self.assertAlmostEqual(arc1.delta, -90.0) - -// self.assertAlmostEqual(arc1.point(0.0), (0j)) -// self.assertAlmostEqual(arc1.point(0.1), (1.23116594049 + 7.82172325201j)) -// self.assertAlmostEqual(arc1.point(0.2), (4.89434837048 + 15.4508497187j)) -// self.assertAlmostEqual(arc1.point(0.3), (10.8993475812 + 22.699524987j)) -// self.assertAlmostEqual(arc1.point(0.4), (19.0983005625 + 29.3892626146j)) -// self.assertAlmostEqual(arc1.point(0.5), (29.2893218813 + 35.3553390593j)) -// self.assertAlmostEqual(arc1.point(0.6), (41.2214747708 + 40.4508497187j)) -// self.assertAlmostEqual(arc1.point(0.7), (54.6009500260 + 44.5503262094j)) -// self.assertAlmostEqual(arc1.point(0.8), (69.0983005625 + 47.5528258148j)) -// self.assertAlmostEqual(arc1.point(0.9), (84.3565534960 + 49.3844170298j)) -// self.assertAlmostEqual(arc1.point(1.0), (100 + 50j)) - -// arc2 = Arc(0j, 100 + 50j, 0, 1, 0, 100 + 50j) -// self.assertAlmostEqual(arc2.center, 50j) -// self.assertAlmostEqual(arc2.theta, 270.0) -// self.assertAlmostEqual(arc2.delta, -270.0) - -// self.assertAlmostEqual(arc2.point(0.0), (0j)) -// self.assertAlmostEqual(arc2.point(0.1), (-45.399049974 + 5.44967379058j)) -// self.assertAlmostEqual(arc2.point(0.2), (-80.9016994375 + 20.6107373854j)) -// self.assertAlmostEqual(arc2.point(0.3), (-98.7688340595 + 42.178276748j)) -// self.assertAlmostEqual(arc2.point(0.4), (-95.1056516295 + 65.4508497187j)) -// self.assertAlmostEqual(arc2.point(0.5), (-70.7106781187 + 85.3553390593j)) -// self.assertAlmostEqual(arc2.point(0.6), (-30.9016994375 + 97.5528258148j)) -// self.assertAlmostEqual(arc2.point(0.7), (15.643446504 + 99.3844170298j)) -// self.assertAlmostEqual(arc2.point(0.8), (58.7785252292 + 90.4508497187j)) -// self.assertAlmostEqual(arc2.point(0.9), (89.1006524188 + 72.699524987j)) -// self.assertAlmostEqual(arc2.point(1.0), (100 + 50j)) - -// arc3 = Arc(0j, 100 + 50j, 0, 0, 1, 100 + 50j) -// self.assertAlmostEqual(arc3.center, 50j) -// self.assertAlmostEqual(arc3.theta, 270.0) -// self.assertAlmostEqual(arc3.delta, 90.0) - -// self.assertAlmostEqual(arc3.point(0.0), (0j)) -// self.assertAlmostEqual(arc3.point(0.1), (15.643446504 + 0.615582970243j)) -// self.assertAlmostEqual(arc3.point(0.2), (30.9016994375 + 2.44717418524j)) -// self.assertAlmostEqual(arc3.point(0.3), (45.399049974 + 5.44967379058j)) -// self.assertAlmostEqual(arc3.point(0.4), (58.7785252292 + 9.54915028125j)) -// self.assertAlmostEqual(arc3.point(0.5), (70.7106781187 + 14.6446609407j)) -// self.assertAlmostEqual(arc3.point(0.6), (80.9016994375 + 20.6107373854j)) -// self.assertAlmostEqual(arc3.point(0.7), (89.1006524188 + 27.300475013j)) -// self.assertAlmostEqual(arc3.point(0.8), (95.1056516295 + 34.5491502813j)) -// self.assertAlmostEqual(arc3.point(0.9), (98.7688340595 + 42.178276748j)) -// self.assertAlmostEqual(arc3.point(1.0), (100 + 50j)) - -// arc4 = Arc(0j, 100 + 50j, 0, 1, 1, 100 + 50j) -// self.assertAlmostEqual(arc4.center, 100 + 0j) -// self.assertAlmostEqual(arc4.theta, 180.0) -// self.assertAlmostEqual(arc4.delta, 270.0) - -// self.assertAlmostEqual(arc4.point(0.0), (0j)) -// self.assertAlmostEqual(arc4.point(0.1), (10.8993475812 - 22.699524987j)) -// self.assertAlmostEqual(arc4.point(0.2), (41.2214747708 - 40.4508497187j)) -// self.assertAlmostEqual(arc4.point(0.3), (84.3565534960 - 49.3844170298j)) -// self.assertAlmostEqual(arc4.point(0.4), (130.901699437 - 47.5528258148j)) -// self.assertAlmostEqual(arc4.point(0.5), (170.710678119 - 35.3553390593j)) -// self.assertAlmostEqual(arc4.point(0.6), (195.105651630 - 15.4508497187j)) -// self.assertAlmostEqual(arc4.point(0.7), (198.768834060 + 7.82172325201j)) -// self.assertAlmostEqual(arc4.point(0.8), (180.901699437 + 29.3892626146j)) -// self.assertAlmostEqual(arc4.point(0.9), (145.399049974 + 44.5503262094j)) -// self.assertAlmostEqual(arc4.point(1.0), (100 + 50j)) - -// def test_length(self): -// # I'll test the length calculations by making a circle, in two parts. -// arc1 = Arc(0j, 100 + 100j, 0, 0, 0, 200 + 0j) -// arc2 = Arc(200 + 0j, 100 + 100j, 0, 0, 0, 0j) -// self.assertAlmostEqual(arc1.length(), pi * 100) -// self.assertAlmostEqual(arc2.length(), pi * 100) - -// def test_length_out_of_range(self): -// # See F.6.2 Out-of-range parameters - -// # If the endpoints (x1, y1) and (x2, y2) are identical, then this is -// # equivalent to omitting the elliptical arc segment entirely. -// arc = Arc(0j, 100 + 100j, 0, 0, 0, 0j) -// self.assertAlmostEqual(arc.length(), 0) - -// # If rx = 0 or ry = 0 then this arc is treated as a straight -// # line segment (a "lineto") joining the endpoints. -// arc = Arc(0j, 0j, 0, 0, 0, 200 + 0j) -// self.assertAlmostEqual(arc.length(), 200) - -// # If rx or ry have negative signs, these are dropped; -// # the absolute value is used instead. -// arc = Arc(200 + 0j, -100 - 100j, 0, 0, 0, 0j) -// self.assertAlmostEqual(arc.length(), pi * 100) - -// # If rx, ry and φ are such that there is no solution (basically, -// # the ellipse is not big enough to reach from (x1, y1) to (x2, y2)) -// # then the ellipse is scaled up uniformly until there is exactly -// # one solution (until the ellipse is just big enough). -// arc = Arc(0j, 1 + 1j, 0, 0, 0, 200 + 0j) -// self.assertAlmostEqual(arc.length(), pi * 100) - -// # φ is taken mod 360 degrees. -// arc = Arc(200 + 0j, -100 - 100j, 720, 0, 0, 0j) -// self.assertAlmostEqual(arc.length(), pi * 100) - -// def test_equality(self): -// # This is to test the __eq__ and __ne__ methods, so we can't use -// # assertEqual and assertNotEqual -// segment = Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) -// self.assertTrue(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j)) -// self.assertTrue(segment != Arc(0j, 100 + 50j, 0, 1, 0, 100 + 50j)) - -// def test_issue25(self): -// # This raised a math domain error -// Arc( -// (725.307482225571 - 915.5548199281527j), -// (202.79421639137703 + 148.77294617167183j), -// 225.6910319606926, -// 1, -// 1, -// (-624.6375539637027 + 896.5483089399895j), -// ) - - -// class TestPath(unittest.TestCase): -// def test_circle(self): -// arc1 = Arc(0j, 100 + 100j, 0, 0, 0, 200 + 0j) -// arc2 = Arc(200 + 0j, 100 + 100j, 0, 0, 0, 0j) -// path = Path(arc1, arc2) -// self.assertAlmostEqual(path.point(0.0), (0j)) -// self.assertAlmostEqual(path.point(0.25), (100 + 100j)) -// self.assertAlmostEqual(path.point(0.5), (200 + 0j)) -// self.assertAlmostEqual(path.point(0.75), (100 - 100j)) -// self.assertAlmostEqual(path.point(1.0), (0j)) -// self.assertAlmostEqual(path.length(), pi * 200) - -// def test_svg_specs(self): -// """The paths that are in the SVG specs""" - -// # Big pie: M300,200 h-150 a150,150 0 1,0 150,-150 z -// path = Path( -// Line(300 + 200j, 150 + 200j), -// Arc(150 + 200j, 150 + 150j, 0, 1, 0, 300 + 50j), -// Line(300 + 50j, 300 + 200j), -// ) -// # The points and length for this path are calculated and not regression tests. -// self.assertAlmostEqual(path.point(0.0), (300 + 200j)) -// self.assertAlmostEqual(path.point(0.14897825542), (150 + 200j)) -// self.assertAlmostEqual(path.point(0.5), (406.066017177 + 306.066017177j)) -// self.assertAlmostEqual(path.point(1 - 0.14897825542), (300 + 50j)) -// self.assertAlmostEqual(path.point(1.0), (300 + 200j)) -// # The errors seem to accumulate. Still 6 decimal places is more than good enough. -// self.assertAlmostEqual(path.length(), pi * 225 + 300, places=6) - -// # Little pie: M275,175 v-150 a150,150 0 0,0 -150,150 z -// path = Path( -// Line(275 + 175j, 275 + 25j), -// Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j), -// Line(125 + 175j, 275 + 175j), -// ) -// # The points and length for this path are calculated and not regression tests. -// self.assertAlmostEqual(path.point(0.0), (275 + 175j)) -// self.assertAlmostEqual(path.point(0.2800495767557787), (275 + 25j)) -// self.assertAlmostEqual( -// path.point(0.5), (168.93398282201787 + 68.93398282201787j) -// ) -// self.assertAlmostEqual(path.point(1 - 0.2800495767557787), (125 + 175j)) -// self.assertAlmostEqual(path.point(1.0), (275 + 175j)) -// # The errors seem to accumulate. Still 6 decimal places is more than good enough. -// self.assertAlmostEqual(path.length(), pi * 75 + 300, places=6) - -// # Bumpy 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 -// path = Path( -// 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), -// ) - -// # These are *not* calculated, but just regression tests. Be skeptical. -// self.assertAlmostEqual(path.point(0.0), (600 + 350j)) -// self.assertAlmostEqual(path.point(0.3), (755.23979927 + 212.1820209585j)) -// self.assertAlmostEqual(path.point(0.5), (827.73074926 + 147.8241574162j)) -// self.assertAlmostEqual(path.point(0.9), (971.28435780 + 106.3023526073j)) -// self.assertAlmostEqual(path.point(1.0), (1050 + 125j)) -// self.assertAlmostEqual(path.length(), 928.388639381) - -// def test_repr(self): -// path = Path( -// Line(start=600 + 350j, end=650 + 325j), -// Arc( -// start=650 + 325j, -// radius=25 + 25j, -// rotation=-30, -// arc=0, -// sweep=1, -// end=700 + 300j, -// ), -// CubicBezier( -// start=700 + 300j, -// control1=800 + 400j, -// control2=750 + 200j, -// end=600 + 100j, -// ), -// QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), -// ) -// self.assertEqual(eval(repr(path)), path) - -// def test_reverse(self): -// # Currently you can't reverse paths. -// self.assertRaises(NotImplementedError, Path().reverse) - -// def test_equality(self): -// # This is to test the __eq__ and __ne__ methods, so we can't use -// # assertEqual and assertNotEqual -// path1 = Path( -// Line(start=600 + 350j, end=650 + 325j), -// Arc( -// start=650 + 325j, -// radius=25 + 25j, -// rotation=-30, -// arc=0, -// sweep=1, -// end=700 + 300j, -// ), -// CubicBezier( -// start=700 + 300j, -// control1=800 + 400j, -// control2=750 + 200j, -// end=600 + 100j, -// ), -// QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), -// ) -// path2 = Path( -// Line(start=600 + 350j, end=650 + 325j), -// Arc( -// start=650 + 325j, -// radius=25 + 25j, -// rotation=-30, -// arc=0, -// sweep=1, -// end=700 + 300j, -// ), -// CubicBezier( -// start=700 + 300j, -// control1=800 + 400j, -// control2=750 + 200j, -// end=600 + 100j, -// ), -// QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), -// ) - -// self.assertTrue(path1 == path2) -// # Modify path2: -// path2[0].start = 601 + 350j -// self.assertTrue(path1 != path2) - -// # Modify back: -// path2[0].start = 600 + 350j -// self.assertFalse(path1 != path2) - -// # Get rid of the last segment: -// del path2[-1] -// self.assertFalse(path1 == path2) - -// # It's not equal to a list of it's segments -// self.assertTrue(path1 != path1[:]) -// self.assertFalse(path1 == path1[:]) - -// def test_non_arc(self): -// # And arc with the same start and end is a noop. -// segment = Arc(0j + 70j, 35 + 35j, 0, 1, 0, 0 + 70j) -// self.assertEqual(segment.length(), 0) -// self.assertEqual(segment.point(0.5), segment.start) - -// def test_zero_paths(self): -// move_only = Path(Move(0)) -// self.assertEqual(move_only.point(0), 0 + 0j) -// self.assertEqual(move_only.point(0.5), 0 + 0j) -// self.assertEqual(move_only.point(1), 0 + 0j) -// self.assertEqual(move_only.length(), 0) - -// move_onlyz = Path(Move(0), Close(0, 0)) -// self.assertEqual(move_onlyz.point(0), 0 + 0j) -// self.assertEqual(move_onlyz.point(0.5), 0 + 0j) -// self.assertEqual(move_onlyz.point(1), 0 + 0j) -// self.assertEqual(move_onlyz.length(), 0) - -// zero_line = Path(Move(0), Line(0, 0)) -// self.assertEqual(zero_line.point(0), 0 + 0j) -// self.assertEqual(zero_line.point(0.5), 0 + 0j) -// self.assertEqual(zero_line.point(1), 0 + 0j) -// self.assertEqual(zero_line.length(), 0) - -// only_line = Path(Line(1 + 1j, 1 + 1j)) -// self.assertEqual(only_line.point(0), 1 + 1j) -// self.assertEqual(only_line.point(0.5), 1 + 1j) -// self.assertEqual(only_line.point(1), 1 + 1j) -// self.assertEqual(only_line.length(), 0) -} \ No newline at end of file + // group('Line tests', () { + + // test('Test lines', () { + + // // These points are calculated, and not just regression tests. + // const line1 = Line(start:Point.zero, end:Point(400, 0)); + // expect(line1.point(0), moreOrLessEquals(0)); + // // expect(line1.point(0.3), moreOrLessEquals(const Point(120, 0))); + // // expect(line1.point(0.5), moreOrLessEquals(const Point(200, 0))); + // // expect(line1.point(0.9), moreOrLessEquals(const Point(360, 0))); + // // expect(line1.point(1), moreOrLessEquals(const Point(400, 0))); + // expect(line1.size(), moreOrLessEquals(400)); + + // const line2 = Line(start: Point(400, 0), end:Point(400, 300)); + // // expect(line2.point(0), (400 + 0j)) + // // expect(line2.point(0.3), (400 + 90j)) + // // expect(line2.point(0.5), (400 + 150j)) + // // expect(line2.point(0.9), (400 + 270j)) + // // expect(line2.point(1), (400 + 300j)) + // expect(line2.size(), moreOrLessEquals(300)); + + // const line3 = Line(start:Point(400, 300), end:Point.zero); + // // expect(line3.point(0), (400 + 300j)) + // // expect(line3.point(0.3), (280 + 210j)) + // // expect(line3.point(0.5), (200 + 150j)) + // // expect(line3.point(0.9), (40 + 30j)) + // // expect(line3.point(1), (0j)) + // expect(line3.size(), moreOrLessEquals(500)); + // }); + + // // def testEquality(self): + // // // This is to test the __eq__ and __ne__ methods, so we can't use + // // // assertEqual and assertNotEqual + // // line = Line(0j, 400 + 0j) + // // self.assertTrue(line == Line(0, 400)) + // // self.assertTrue(line != Line(100, 400)) + // // self.assertFalse(line == str(line)) + // // self.assertTrue(line != str(line)) + // // self.assertFalse( + // // CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) == line + // // ) + + // }); + + // // class CubicBezierTest(unittest.TestCase): + // // def test_approx_circle(self): + // // """This is a approximate circle drawn in Inkscape""" + + // // arc1 = CubicBezier( + // // complex(0, 0), + // // complex(0, 109.66797), + // // complex(-88.90345, 198.57142), + // // complex(-198.57142, 198.57142), + // // ) + + // // self.assertAlmostEqual(arc1.point(0), (0j)) + // // self.assertAlmostEqual(arc1.point(0.1), (-2.59896457 + 32.20931647j)) + // // self.assertAlmostEqual(arc1.point(0.2), (-10.12330256 + 62.76392816j)) + // // self.assertAlmostEqual(arc1.point(0.3), (-22.16418039 + 91.25500149j)) + // // self.assertAlmostEqual(arc1.point(0.4), (-38.31276448 + 117.27370288j)) + // // self.assertAlmostEqual(arc1.point(0.5), (-58.16022125 + 140.41119875j)) + // // self.assertAlmostEqual(arc1.point(0.6), (-81.29771712 + 160.25865552j)) + // // self.assertAlmostEqual(arc1.point(0.7), (-107.31641851 + 176.40723961j)) + // // self.assertAlmostEqual(arc1.point(0.8), (-135.80749184 + 188.44811744j)) + // // self.assertAlmostEqual(arc1.point(0.9), (-166.36210353 + 195.97245543j)) + // // self.assertAlmostEqual(arc1.point(1), (-198.57142 + 198.57142j)) + + // // arc2 = CubicBezier( + // // complex(-198.57142, 198.57142), + // // complex(-109.66797 - 198.57142, 0 + 198.57142), + // // complex(-198.57143 - 198.57142, -88.90345 + 198.57142), + // // complex(-198.57143 - 198.57142, 0), + // // ) + + // // self.assertAlmostEqual(arc2.point(0), (-198.57142 + 198.57142j)) + // // self.assertAlmostEqual(arc2.point(0.1), (-230.78073675 + 195.97245543j)) + // // self.assertAlmostEqual(arc2.point(0.2), (-261.3353492 + 188.44811744j)) + // // self.assertAlmostEqual(arc2.point(0.3), (-289.82642365 + 176.40723961j)) + // // self.assertAlmostEqual(arc2.point(0.4), (-315.8451264 + 160.25865552j)) + // // self.assertAlmostEqual(arc2.point(0.5), (-338.98262375 + 140.41119875j)) + // // self.assertAlmostEqual(arc2.point(0.6), (-358.830082 + 117.27370288j)) + // // self.assertAlmostEqual(arc2.point(0.7), (-374.97866745 + 91.25500149j)) + // // self.assertAlmostEqual(arc2.point(0.8), (-387.0195464 + 62.76392816j)) + // // self.assertAlmostEqual(arc2.point(0.9), (-394.54388515 + 32.20931647j)) + // // self.assertAlmostEqual(arc2.point(1), (-397.14285 + 0j)) + + // // arc3 = CubicBezier( + // // complex(-198.57143 - 198.57142, 0), + // // complex(0 - 198.57143 - 198.57142, -109.66797), + // // complex(88.90346 - 198.57143 - 198.57142, -198.57143), + // // complex(-198.57142, -198.57143), + // // ) + + // // self.assertAlmostEqual(arc3.point(0), (-397.14285 + 0j)) + // // self.assertAlmostEqual(arc3.point(0.1), (-394.54388515 - 32.20931675j)) + // // self.assertAlmostEqual(arc3.point(0.2), (-387.0195464 - 62.7639292j)) + // // self.assertAlmostEqual(arc3.point(0.3), (-374.97866745 - 91.25500365j)) + // // self.assertAlmostEqual(arc3.point(0.4), (-358.830082 - 117.2737064j)) + // // self.assertAlmostEqual(arc3.point(0.5), (-338.98262375 - 140.41120375j)) + // // self.assertAlmostEqual(arc3.point(0.6), (-315.8451264 - 160.258662j)) + // // self.assertAlmostEqual(arc3.point(0.7), (-289.82642365 - 176.40724745j)) + // // self.assertAlmostEqual(arc3.point(0.8), (-261.3353492 - 188.4481264j)) + // // self.assertAlmostEqual(arc3.point(0.9), (-230.78073675 - 195.97246515j)) + // // self.assertAlmostEqual(arc3.point(1), (-198.57142 - 198.57143j)) + + // // arc4 = CubicBezier( + // // complex(-198.57142, -198.57143), + // // complex(109.66797 - 198.57142, 0 - 198.57143), + // // complex(0, 88.90346 - 198.57143), + // // complex(0, 0), + // // ) + + // // self.assertAlmostEqual(arc4.point(0), (-198.57142 - 198.57143j)) + // // self.assertAlmostEqual(arc4.point(0.1), (-166.36210353 - 195.97246515j)) + // // self.assertAlmostEqual(arc4.point(0.2), (-135.80749184 - 188.4481264j)) + // // self.assertAlmostEqual(arc4.point(0.3), (-107.31641851 - 176.40724745j)) + // // self.assertAlmostEqual(arc4.point(0.4), (-81.29771712 - 160.258662j)) + // // self.assertAlmostEqual(arc4.point(0.5), (-58.16022125 - 140.41120375j)) + // // self.assertAlmostEqual(arc4.point(0.6), (-38.31276448 - 117.2737064j)) + // // self.assertAlmostEqual(arc4.point(0.7), (-22.16418039 - 91.25500365j)) + // // self.assertAlmostEqual(arc4.point(0.8), (-10.12330256 - 62.7639292j)) + // // self.assertAlmostEqual(arc4.point(0.9), (-2.59896457 - 32.20931675j)) + // // self.assertAlmostEqual(arc4.point(1), (0j)) + + // // def test_svg_examples(self): + + // // # M100,200 C100,100 250,100 250,200 + // // path1 = CubicBezier(100 + 200j, 100 + 100j, 250 + 100j, 250 + 200j) + // // self.assertAlmostEqual(path1.point(0), (100 + 200j)) + // // self.assertAlmostEqual(path1.point(0.3), (132.4 + 137j)) + // // self.assertAlmostEqual(path1.point(0.5), (175 + 125j)) + // // self.assertAlmostEqual(path1.point(0.9), (245.8 + 173j)) + // // self.assertAlmostEqual(path1.point(1), (250 + 200j)) + + // // # S400,300 400,200 + // // path2 = CubicBezier(250 + 200j, 250 + 300j, 400 + 300j, 400 + 200j) + // // self.assertAlmostEqual(path2.point(0), (250 + 200j)) + // // self.assertAlmostEqual(path2.point(0.3), (282.4 + 263j)) + // // self.assertAlmostEqual(path2.point(0.5), (325 + 275j)) + // // self.assertAlmostEqual(path2.point(0.9), (395.8 + 227j)) + // // self.assertAlmostEqual(path2.point(1), (400 + 200j)) + + // // # M100,200 C100,100 400,100 400,200 + // // path3 = CubicBezier(100 + 200j, 100 + 100j, 400 + 100j, 400 + 200j) + // // self.assertAlmostEqual(path3.point(0), (100 + 200j)) + // // self.assertAlmostEqual(path3.point(0.3), (164.8 + 137j)) + // // self.assertAlmostEqual(path3.point(0.5), (250 + 125j)) + // // self.assertAlmostEqual(path3.point(0.9), (391.6 + 173j)) + // // self.assertAlmostEqual(path3.point(1), (400 + 200j)) + + // // # M100,500 C25,400 475,400 400,500 + // // path4 = CubicBezier(100 + 500j, 25 + 400j, 475 + 400j, 400 + 500j) + // // self.assertAlmostEqual(path4.point(0), (100 + 500j)) + // // self.assertAlmostEqual(path4.point(0.3), (145.9 + 437j)) + // // self.assertAlmostEqual(path4.point(0.5), (250 + 425j)) + // // self.assertAlmostEqual(path4.point(0.9), (407.8 + 473j)) + // // self.assertAlmostEqual(path4.point(1), (400 + 500j)) + + // // # M100,800 C175,700 325,700 400,800 + // // path5 = CubicBezier(100 + 800j, 175 + 700j, 325 + 700j, 400 + 800j) + // // self.assertAlmostEqual(path5.point(0), (100 + 800j)) + // // self.assertAlmostEqual(path5.point(0.3), (183.7 + 737j)) + // // self.assertAlmostEqual(path5.point(0.5), (250 + 725j)) + // // self.assertAlmostEqual(path5.point(0.9), (375.4 + 773j)) + // // self.assertAlmostEqual(path5.point(1), (400 + 800j)) + + // // # M600,200 C675,100 975,100 900,200 + // // path6 = CubicBezier(600 + 200j, 675 + 100j, 975 + 100j, 900 + 200j) + // // self.assertAlmostEqual(path6.point(0), (600 + 200j)) + // // self.assertAlmostEqual(path6.point(0.3), (712.05 + 137j)) + // // self.assertAlmostEqual(path6.point(0.5), (806.25 + 125j)) + // // self.assertAlmostEqual(path6.point(0.9), (911.85 + 173j)) + // // self.assertAlmostEqual(path6.point(1), (900 + 200j)) + + // // # M600,500 C600,350 900,650 900,500 + // // path7 = CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) + // // self.assertAlmostEqual(path7.point(0), (600 + 500j)) + // // self.assertAlmostEqual(path7.point(0.3), (664.8 + 462.2j)) + // // self.assertAlmostEqual(path7.point(0.5), (750 + 500j)) + // // self.assertAlmostEqual(path7.point(0.9), (891.6 + 532.4j)) + // // self.assertAlmostEqual(path7.point(1), (900 + 500j)) + + // // # M600,800 C625,700 725,700 750,800 + // // path8 = CubicBezier(600 + 800j, 625 + 700j, 725 + 700j, 750 + 800j) + // // self.assertAlmostEqual(path8.point(0), (600 + 800j)) + // // self.assertAlmostEqual(path8.point(0.3), (638.7 + 737j)) + // // self.assertAlmostEqual(path8.point(0.5), (675 + 725j)) + // // self.assertAlmostEqual(path8.point(0.9), (740.4 + 773j)) + // // self.assertAlmostEqual(path8.point(1), (750 + 800j)) + + // // # S875,900 900,800 + // // inversion = (750 + 800j) + (750 + 800j) - (725 + 700j) + // // path9 = CubicBezier(750 + 800j, inversion, 875 + 900j, 900 + 800j) + // // self.assertAlmostEqual(path9.point(0), (750 + 800j)) + // // self.assertAlmostEqual(path9.point(0.3), (788.7 + 863j)) + // // self.assertAlmostEqual(path9.point(0.5), (825 + 875j)) + // // self.assertAlmostEqual(path9.point(0.9), (890.4 + 827j)) + // // self.assertAlmostEqual(path9.point(1), (900 + 800j)) + + // // def test_length(self): + + // // # A straight line: + // // arc = CubicBezier( + // // complex(0, 0), complex(0, 0), complex(0, 100), complex(0, 100) + // // ) + + // // self.assertAlmostEqual(arc.length(), 100) + + // // # A diagonal line: + // // arc = CubicBezier( + // // complex(0, 0), complex(0, 0), complex(100, 100), complex(100, 100) + // // ) + + // // self.assertAlmostEqual(arc.length(), sqrt(2 * 100 * 100)) + + // // # A quarter circle arc with radius 100: + // // kappa = ( + // // 4 * (sqrt(2) - 1) / 3 + // // ) # http://www.whizkidtech.redprince.net/bezier/circle/ + + // // arc = CubicBezier( + // // complex(0, 0), + // // complex(0, kappa * 100), + // // complex(100 - kappa * 100, 100), + // // complex(100, 100), + // // ) + + // // # We can't compare with pi*50 here, because this is just an + // // # approximation of a circle arc. pi*50 is 157.079632679 + // // # So this is just yet another "warn if this changes" test. + // // # This value is not verified to be correct. + // // self.assertAlmostEqual(arc.length(), 157.1016698) + + // // # A recursive solution has also been suggested, but for CubicBezier + // // # curves it could get a false solution on curves where the midpoint is on a + // // # straight line between the start and end. For example, the following + // // # curve would get solved as a straight line and get the length 300. + // // # Make sure this is not the case. + // // arc = CubicBezier( + // // complex(600, 500), complex(600, 350), complex(900, 650), complex(900, 500) + // // ) + // // self.assertTrue(arc.length() > 300.0) + + // // def test_equality(self): + // // # This is to test the __eq__ and __ne__ methods, so we can't use + // // # assertEqual and assertNotEqual + // // segment = CubicBezier( + // // complex(600, 500), complex(600, 350), complex(900, 650), complex(900, 500) + // // ) + + // // self.assertTrue( + // // segment == CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) + // // ) + // // self.assertTrue( + // // segment != CubicBezier(600 + 501j, 600 + 350j, 900 + 650j, 900 + 500j) + // // ) + // // self.assertTrue(segment != Line(0, 400)) + + // // class QuadraticBezierTest(unittest.TestCase): + // // def test_svg_examples(self): + // // """These is the path in the SVG specs""" + // // # M200,300 Q400,50 600,300 T1000,300 + // // path1 = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) + // // self.assertAlmostEqual(path1.point(0), (200 + 300j)) + // // self.assertAlmostEqual(path1.point(0.3), (320 + 195j)) + // // self.assertAlmostEqual(path1.point(0.5), (400 + 175j)) + // // self.assertAlmostEqual(path1.point(0.9), (560 + 255j)) + // // self.assertAlmostEqual(path1.point(1), (600 + 300j)) + + // // # T1000, 300 + // // inversion = (600 + 300j) + (600 + 300j) - (400 + 50j) + // // path2 = QuadraticBezier(600 + 300j, inversion, 1000 + 300j) + // // self.assertAlmostEqual(path2.point(0), (600 + 300j)) + // // self.assertAlmostEqual(path2.point(0.3), (720 + 405j)) + // // self.assertAlmostEqual(path2.point(0.5), (800 + 425j)) + // // self.assertAlmostEqual(path2.point(0.9), (960 + 345j)) + // // self.assertAlmostEqual(path2.point(1), (1000 + 300j)) + + // // def test_length(self): + // // # expected results calculated with + // // # svg.path.segment_length(q, 0, 1, q.start, q.end, 1e-14, 20, 0) + // // q1 = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) + // // q2 = QuadraticBezier(200 + 300j, 400 + 50j, 500 + 200j) + // // closedq = QuadraticBezier(6 + 2j, 5 - 1j, 6 + 2j) + // // linq1 = QuadraticBezier(1, 2, 3) + // // linq2 = QuadraticBezier(1 + 3j, 2 + 5j, -9 - 17j) + // // nodalq = QuadraticBezier(1, 1, 1) + // // tests = [ + // // (q1, 487.77109389525975), + // // (q2, 379.90458193489155), + // // (closedq, 3.1622776601683795), + // // (linq1, 2), + // // (linq2, 22.73335777124786), + // // (nodalq, 0), + // // ] + // // for q, exp_res in tests: + // // self.assertAlmostEqual(q.length(), exp_res) + + // // def test_equality(self): + // // # This is to test the __eq__ and __ne__ methods, so we can't use + // // # assertEqual and assertNotEqual + // // segment = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j) + // // self.assertTrue(segment == QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j)) + // // self.assertTrue(segment != QuadraticBezier(200 + 301j, 400 + 50j, 600 + 300j)) + // // self.assertFalse(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j)) + // // self.assertTrue(Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) != segment) + + // // class ArcTest(unittest.TestCase): + // // def test_points(self): + // // arc1 = Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) + // // self.assertAlmostEqual(arc1.center, 100 + 0j) + // // self.assertAlmostEqual(arc1.theta, 180.0) + // // self.assertAlmostEqual(arc1.delta, -90.0) + + // // self.assertAlmostEqual(arc1.point(0.0), (0j)) + // // self.assertAlmostEqual(arc1.point(0.1), (1.23116594049 + 7.82172325201j)) + // // self.assertAlmostEqual(arc1.point(0.2), (4.89434837048 + 15.4508497187j)) + // // self.assertAlmostEqual(arc1.point(0.3), (10.8993475812 + 22.699524987j)) + // // self.assertAlmostEqual(arc1.point(0.4), (19.0983005625 + 29.3892626146j)) + // // self.assertAlmostEqual(arc1.point(0.5), (29.2893218813 + 35.3553390593j)) + // // self.assertAlmostEqual(arc1.point(0.6), (41.2214747708 + 40.4508497187j)) + // // self.assertAlmostEqual(arc1.point(0.7), (54.6009500260 + 44.5503262094j)) + // // self.assertAlmostEqual(arc1.point(0.8), (69.0983005625 + 47.5528258148j)) + // // self.assertAlmostEqual(arc1.point(0.9), (84.3565534960 + 49.3844170298j)) + // // self.assertAlmostEqual(arc1.point(1.0), (100 + 50j)) + + // // arc2 = Arc(0j, 100 + 50j, 0, 1, 0, 100 + 50j) + // // self.assertAlmostEqual(arc2.center, 50j) + // // self.assertAlmostEqual(arc2.theta, 270.0) + // // self.assertAlmostEqual(arc2.delta, -270.0) + + // // self.assertAlmostEqual(arc2.point(0.0), (0j)) + // // self.assertAlmostEqual(arc2.point(0.1), (-45.399049974 + 5.44967379058j)) + // // self.assertAlmostEqual(arc2.point(0.2), (-80.9016994375 + 20.6107373854j)) + // // self.assertAlmostEqual(arc2.point(0.3), (-98.7688340595 + 42.178276748j)) + // // self.assertAlmostEqual(arc2.point(0.4), (-95.1056516295 + 65.4508497187j)) + // // self.assertAlmostEqual(arc2.point(0.5), (-70.7106781187 + 85.3553390593j)) + // // self.assertAlmostEqual(arc2.point(0.6), (-30.9016994375 + 97.5528258148j)) + // // self.assertAlmostEqual(arc2.point(0.7), (15.643446504 + 99.3844170298j)) + // // self.assertAlmostEqual(arc2.point(0.8), (58.7785252292 + 90.4508497187j)) + // // self.assertAlmostEqual(arc2.point(0.9), (89.1006524188 + 72.699524987j)) + // // self.assertAlmostEqual(arc2.point(1.0), (100 + 50j)) + + // // arc3 = Arc(0j, 100 + 50j, 0, 0, 1, 100 + 50j) + // // self.assertAlmostEqual(arc3.center, 50j) + // // self.assertAlmostEqual(arc3.theta, 270.0) + // // self.assertAlmostEqual(arc3.delta, 90.0) + + // // self.assertAlmostEqual(arc3.point(0.0), (0j)) + // // self.assertAlmostEqual(arc3.point(0.1), (15.643446504 + 0.615582970243j)) + // // self.assertAlmostEqual(arc3.point(0.2), (30.9016994375 + 2.44717418524j)) + // // self.assertAlmostEqual(arc3.point(0.3), (45.399049974 + 5.44967379058j)) + // // self.assertAlmostEqual(arc3.point(0.4), (58.7785252292 + 9.54915028125j)) + // // self.assertAlmostEqual(arc3.point(0.5), (70.7106781187 + 14.6446609407j)) + // // self.assertAlmostEqual(arc3.point(0.6), (80.9016994375 + 20.6107373854j)) + // // self.assertAlmostEqual(arc3.point(0.7), (89.1006524188 + 27.300475013j)) + // // self.assertAlmostEqual(arc3.point(0.8), (95.1056516295 + 34.5491502813j)) + // // self.assertAlmostEqual(arc3.point(0.9), (98.7688340595 + 42.178276748j)) + // // self.assertAlmostEqual(arc3.point(1.0), (100 + 50j)) + + // // arc4 = Arc(0j, 100 + 50j, 0, 1, 1, 100 + 50j) + // // self.assertAlmostEqual(arc4.center, 100 + 0j) + // // self.assertAlmostEqual(arc4.theta, 180.0) + // // self.assertAlmostEqual(arc4.delta, 270.0) + + // // self.assertAlmostEqual(arc4.point(0.0), (0j)) + // // self.assertAlmostEqual(arc4.point(0.1), (10.8993475812 - 22.699524987j)) + // // self.assertAlmostEqual(arc4.point(0.2), (41.2214747708 - 40.4508497187j)) + // // self.assertAlmostEqual(arc4.point(0.3), (84.3565534960 - 49.3844170298j)) + // // self.assertAlmostEqual(arc4.point(0.4), (130.901699437 - 47.5528258148j)) + // // self.assertAlmostEqual(arc4.point(0.5), (170.710678119 - 35.3553390593j)) + // // self.assertAlmostEqual(arc4.point(0.6), (195.105651630 - 15.4508497187j)) + // // self.assertAlmostEqual(arc4.point(0.7), (198.768834060 + 7.82172325201j)) + // // self.assertAlmostEqual(arc4.point(0.8), (180.901699437 + 29.3892626146j)) + // // self.assertAlmostEqual(arc4.point(0.9), (145.399049974 + 44.5503262094j)) + // // self.assertAlmostEqual(arc4.point(1.0), (100 + 50j)) + + // // def test_length(self): + // // # I'll test the length calculations by making a circle, in two parts. + // // arc1 = Arc(0j, 100 + 100j, 0, 0, 0, 200 + 0j) + // // arc2 = Arc(200 + 0j, 100 + 100j, 0, 0, 0, 0j) + // // self.assertAlmostEqual(arc1.length(), pi * 100) + // // self.assertAlmostEqual(arc2.length(), pi * 100) + + // // def test_length_out_of_range(self): + // // # See F.6.2 Out-of-range parameters + + // // # If the endpoints (x1, y1) and (x2, y2) are identical, then this is + // // # equivalent to omitting the elliptical arc segment entirely. + // // arc = Arc(0j, 100 + 100j, 0, 0, 0, 0j) + // // self.assertAlmostEqual(arc.length(), 0) + + // // # If rx = 0 or ry = 0 then this arc is treated as a straight + // // # line segment (a "lineto") joining the endpoints. + // // arc = Arc(0j, 0j, 0, 0, 0, 200 + 0j) + // // self.assertAlmostEqual(arc.length(), 200) + + // // # If rx or ry have negative signs, these are dropped; + // // # the absolute value is used instead. + // // arc = Arc(200 + 0j, -100 - 100j, 0, 0, 0, 0j) + // // self.assertAlmostEqual(arc.length(), pi * 100) + + // // # If rx, ry and φ are such that there is no solution (basically, + // // # the ellipse is not big enough to reach from (x1, y1) to (x2, y2)) + // // # then the ellipse is scaled up uniformly until there is exactly + // // # one solution (until the ellipse is just big enough). + // // arc = Arc(0j, 1 + 1j, 0, 0, 0, 200 + 0j) + // // self.assertAlmostEqual(arc.length(), pi * 100) + + // // # φ is taken mod 360 degrees. + // // arc = Arc(200 + 0j, -100 - 100j, 720, 0, 0, 0j) + // // self.assertAlmostEqual(arc.length(), pi * 100) + + // // def test_equality(self): + // // # This is to test the __eq__ and __ne__ methods, so we can't use + // // # assertEqual and assertNotEqual + // // segment = Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) + // // self.assertTrue(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j)) + // // self.assertTrue(segment != Arc(0j, 100 + 50j, 0, 1, 0, 100 + 50j)) + + // // def test_issue25(self): + // // # This raised a math domain error + // // Arc( + // // (725.307482225571 - 915.5548199281527j), + // // (202.79421639137703 + 148.77294617167183j), + // // 225.6910319606926, + // // 1, + // // 1, + // // (-624.6375539637027 + 896.5483089399895j), + // // ) + + // // class TestPath(unittest.TestCase): + // // def test_circle(self): + // // arc1 = Arc(0j, 100 + 100j, 0, 0, 0, 200 + 0j) + // // arc2 = Arc(200 + 0j, 100 + 100j, 0, 0, 0, 0j) + // // path = Path(arc1, arc2) + // // self.assertAlmostEqual(path.point(0.0), (0j)) + // // self.assertAlmostEqual(path.point(0.25), (100 + 100j)) + // // self.assertAlmostEqual(path.point(0.5), (200 + 0j)) + // // self.assertAlmostEqual(path.point(0.75), (100 - 100j)) + // // self.assertAlmostEqual(path.point(1.0), (0j)) + // // self.assertAlmostEqual(path.length(), pi * 200) + + // // def test_svg_specs(self): + // // """The paths that are in the SVG specs""" + + // // # Big pie: M300,200 h-150 a150,150 0 1,0 150,-150 z + // // path = Path( + // // Line(300 + 200j, 150 + 200j), + // // Arc(150 + 200j, 150 + 150j, 0, 1, 0, 300 + 50j), + // // Line(300 + 50j, 300 + 200j), + // // ) + // // # The points and length for this path are calculated and not regression tests. + // // self.assertAlmostEqual(path.point(0.0), (300 + 200j)) + // // self.assertAlmostEqual(path.point(0.14897825542), (150 + 200j)) + // // self.assertAlmostEqual(path.point(0.5), (406.066017177 + 306.066017177j)) + // // self.assertAlmostEqual(path.point(1 - 0.14897825542), (300 + 50j)) + // // self.assertAlmostEqual(path.point(1.0), (300 + 200j)) + // // # The errors seem to accumulate. Still 6 decimal places is more than good enough. + // // self.assertAlmostEqual(path.length(), pi * 225 + 300, places=6) + + // // # Little pie: M275,175 v-150 a150,150 0 0,0 -150,150 z + // // path = Path( + // // Line(275 + 175j, 275 + 25j), + // // Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j), + // // Line(125 + 175j, 275 + 175j), + // // ) + // // # The points and length for this path are calculated and not regression tests. + // // self.assertAlmostEqual(path.point(0.0), (275 + 175j)) + // // self.assertAlmostEqual(path.point(0.2800495767557787), (275 + 25j)) + // // self.assertAlmostEqual( + // // path.point(0.5), (168.93398282201787 + 68.93398282201787j) + // // ) + // // self.assertAlmostEqual(path.point(1 - 0.2800495767557787), (125 + 175j)) + // // self.assertAlmostEqual(path.point(1.0), (275 + 175j)) + // // # The errors seem to accumulate. Still 6 decimal places is more than good enough. + // // self.assertAlmostEqual(path.length(), pi * 75 + 300, places=6) + + // // # Bumpy 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 + // // path = Path( + // // 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), + // // ) + + // // # These are *not* calculated, but just regression tests. Be skeptical. + // // self.assertAlmostEqual(path.point(0.0), (600 + 350j)) + // // self.assertAlmostEqual(path.point(0.3), (755.23979927 + 212.1820209585j)) + // // self.assertAlmostEqual(path.point(0.5), (827.73074926 + 147.8241574162j)) + // // self.assertAlmostEqual(path.point(0.9), (971.28435780 + 106.3023526073j)) + // // self.assertAlmostEqual(path.point(1.0), (1050 + 125j)) + // // self.assertAlmostEqual(path.length(), 928.388639381) + + // // def test_repr(self): + // // path = Path( + // // Line(start=600 + 350j, end=650 + 325j), + // // Arc( + // // start=650 + 325j, + // // radius=25 + 25j, + // // rotation=-30, + // // arc=0, + // // sweep=1, + // // end=700 + 300j, + // // ), + // // CubicBezier( + // // start=700 + 300j, + // // control1=800 + 400j, + // // control2=750 + 200j, + // // end=600 + 100j, + // // ), + // // QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), + // // ) + // // self.assertEqual(eval(repr(path)), path) + + // // def test_reverse(self): + // // # Currently you can't reverse paths. + // // self.assertRaises(NotImplementedError, Path().reverse) + + // // def test_equality(self): + // // # This is to test the __eq__ and __ne__ methods, so we can't use + // // # assertEqual and assertNotEqual + // // path1 = Path( + // // Line(start=600 + 350j, end=650 + 325j), + // // Arc( + // // start=650 + 325j, + // // radius=25 + 25j, + // // rotation=-30, + // // arc=0, + // // sweep=1, + // // end=700 + 300j, + // // ), + // // CubicBezier( + // // start=700 + 300j, + // // control1=800 + 400j, + // // control2=750 + 200j, + // // end=600 + 100j, + // // ), + // // QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), + // // ) + // // path2 = Path( + // // Line(start=600 + 350j, end=650 + 325j), + // // Arc( + // // start=650 + 325j, + // // radius=25 + 25j, + // // rotation=-30, + // // arc=0, + // // sweep=1, + // // end=700 + 300j, + // // ), + // // CubicBezier( + // // start=700 + 300j, + // // control1=800 + 400j, + // // control2=750 + 200j, + // // end=600 + 100j, + // // ), + // // QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j), + // // ) + + // // self.assertTrue(path1 == path2) + // // # Modify path2: + // // path2[0].start = 601 + 350j + // // self.assertTrue(path1 != path2) + + // // # Modify back: + // // path2[0].start = 600 + 350j + // // self.assertFalse(path1 != path2) + + // // # Get rid of the last segment: + // // del path2[-1] + // // self.assertFalse(path1 == path2) + + // // # It's not equal to a list of it's segments + // // self.assertTrue(path1 != path1[:]) + // // self.assertFalse(path1 == path1[:]) + + // // def test_non_arc(self): + // // # And arc with the same start and end is a noop. + // // segment = Arc(0j + 70j, 35 + 35j, 0, 1, 0, 0 + 70j) + // // self.assertEqual(segment.length(), 0) + // // self.assertEqual(segment.point(0.5), segment.start) + + // // def test_zero_paths(self): + // // move_only = Path(Move(0)) + // // self.assertEqual(move_only.point(0), 0 + 0j) + // // self.assertEqual(move_only.point(0.5), 0 + 0j) + // // self.assertEqual(move_only.point(1), 0 + 0j) + // // self.assertEqual(move_only.length(), 0) + + // // move_onlyz = Path(Move(0), Close(0, 0)) + // // self.assertEqual(move_onlyz.point(0), 0 + 0j) + // // self.assertEqual(move_onlyz.point(0.5), 0 + 0j) + // // self.assertEqual(move_onlyz.point(1), 0 + 0j) + // // self.assertEqual(move_onlyz.length(), 0) + + // // zero_line = Path(Move(0), Line(0, 0)) + // // self.assertEqual(zero_line.point(0), 0 + 0j) + // // self.assertEqual(zero_line.point(0.5), 0 + 0j) + // // self.assertEqual(zero_line.point(1), 0 + 0j) + // // self.assertEqual(zero_line.length(), 0) + + // // only_line = Path(Line(1 + 1j, 1 + 1j)) + // // self.assertEqual(only_line.point(0), 1 + 1j) + // // self.assertEqual(only_line.point(0.5), 1 + 1j) + // // self.assertEqual(only_line.point(1), 1 + 1j) + // // self.assertEqual(only_line.length(), 0) +} diff --git a/test/svg/tokenizer_test.dart b/test/svg/tokenizer_test.dart index 7e2cb43..d8d1a6c 100644 --- a/test/svg/tokenizer_test.dart +++ b/test/svg/tokenizer_test.dart @@ -3,7 +3,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:kanimaji/common/point.dart'; -import 'package:kanimaji/svg/parser.dart' show Command, Token, commandifyPath, parsePath, tokenizePath; +import 'package:kanimaji/svg/parser.dart' + show Command, Token, commandifyPath, parsePath, tokenizePath; class TokenizerTest { final String pathdef; @@ -30,7 +31,7 @@ final List tokenizerTests = [ Token(command: "M", args: [Point(100, 100)]), Token(command: "L", args: [Point(300, 100)]), Token(command: "L", args: [Point(200, 300)]), - Token(command: "z", args: []) + Token(command: "z", args: []), ], ), const TokenizerTest( @@ -42,17 +43,22 @@ final List tokenizerTests = [ Command(command: "M", args: "5 1"), Command(command: "v", args: "7.344"), Command( - command: "A", args: "3.574 3.574 0 003.5 8 3.515 3.515 0 000 11.5"), + command: "A", + args: "3.574 3.574 0 003.5 8 3.515 3.515 0 000 11.5", + ), Command(command: "C", args: "0 13.421 1.579 15 3.5 15"), Command(command: "A", args: "3.517 3.517 0 007 11.531"), Command(command: "v", args: "-7.53"), Command(command: "h", args: "6"), Command(command: "v", args: "4.343"), Command( - command: "A", args: "3.574 3.574 0 0011.5 8 3.515 3.515 0 008 11.5"), + command: "A", + args: "3.574 3.574 0 0011.5 8 3.515 3.515 0 008 11.5", + ), Command( - command: "c", - args: "0 1.921 1.579 3.5 3.5 3.5 1.9 0 3.465 -1.546 3.5 -3.437"), + command: "c", + args: "0 1.921 1.579 3.5 3.5 3.5 1.9 0 3.465 -1.546 3.5 -3.437", + ), Command(command: "V", args: "1"), Command(command: "z", args: ""), ], @@ -61,26 +67,36 @@ final List tokenizerTests = [ Token(command: "v", args: [7.344]), Token(command: "A", args: [3.574, 3.574, 0, false, false, Point(3.5, 8)]), Token( - command: "A", args: [3.515, 3.515, 0, false, false, Point(0, 11.5)]), + command: "A", + args: [3.515, 3.515, 0, false, false, Point(0, 11.5)], + ), Token( - command: "C", - args: [Point(0, 13.421), Point(1.579, 15), Point(3.5, 15)]), + command: "C", + args: [Point(0, 13.421), Point(1.579, 15), Point(3.5, 15)], + ), Token( - command: "A", - args: [3.517, 3.517, 0, false, false, Point(7, 11.531)]), + command: "A", + args: [3.517, 3.517, 0, false, false, Point(7, 11.531)], + ), Token(command: "v", args: [-7.53]), Token(command: "h", args: [6]), Token(command: "v", args: [4.343]), Token( - command: "A", args: [3.574, 3.574, 0, false, false, Point(11.5, 8)]), + command: "A", + args: [3.574, 3.574, 0, false, false, Point(11.5, 8)], + ), Token( - command: "A", args: [3.515, 3.515, 0, false, false, Point(8, 11.5)]), + command: "A", + args: [3.515, 3.515, 0, false, false, Point(8, 11.5)], + ), Token( - command: "c", - args: [Point(0, 1.921), Point(1.579, 3.5), Point(3.5, 3.5)]), + command: "c", + args: [Point(0, 1.921), Point(1.579, 3.5), Point(3.5, 3.5)], + ), Token( - command: "c", - args: [Point(1.9, 0), Point(3.465, -1.546), Point(3.5, -3.437)]), + command: "c", + args: [Point(1.9, 0), Point(3.465, -1.546), Point(3.5, -3.437)], + ), Token(command: "V", args: [1]), Token(command: "z", args: []), ], @@ -120,4 +136,4 @@ void main() { parsePath(tokenizerTest.pathdef); } }); -} \ No newline at end of file +}