diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 80fdf80eda..d152f35a5a 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -166,6 +166,7 @@ Future _runTests() async { await _runAllDartTests(path.join(flutterRoot, 'dev', 'devicelab')); await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests')); + await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool')); await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world')); await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers')); await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks')); diff --git a/dev/tools/vitool/.gitignore b/dev/tools/vitool/.gitignore new file mode 100644 index 0000000000..1410a619fc --- /dev/null +++ b/dev/tools/vitool/.gitignore @@ -0,0 +1,9 @@ +# Files and directories created by pub +.packages +.pub/ +build/ +# Remove the following pattern if you wish to check in your lock file +pubspec.lock + +# Directory created by dartdoc +doc/api/ diff --git a/dev/tools/vitool/README.md b/dev/tools/vitool/README.md new file mode 100644 index 0000000000..adc2a07049 --- /dev/null +++ b/dev/tools/vitool/README.md @@ -0,0 +1,13 @@ +# vitool + +This tool generates Dart files from frames described in SVG files that follow +the small subset of SVG described below. +This tool was crafted specifically to handle the assets for certain Material +design animations as created by the Google Material Design team, and is not +intended to be a general-purpose tool. + +## Supported SVG features + - groups + - group transforms + - group opacities + - paths (strokes are not supported, only fills, eliptical arc curve commands are not supported) diff --git a/dev/tools/vitool/bin/main.dart b/dev/tools/vitool/bin/main.dart new file mode 100644 index 0000000000..cafeab3a01 --- /dev/null +++ b/dev/tools/vitool/bin/main.dart @@ -0,0 +1,97 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:vitool/vitool.dart'; + +const String kCodegenComment = + '// AUTOGENERATED FILE DO NOT EDIT!\n' + '// This file was generated by vitool.\n'; + +void main(List args) { + final ArgParser parser = new ArgParser(); + + parser.addFlag( + 'help', + abbr: 'h', + negatable: false, + help: 'Display the tool\'s usage instructions and quit.' + ); + + parser.addOption( + 'output', + abbr: 'o', + help: 'Target path to write the generated Dart file to.' + ); + + parser.addOption( + 'asset-name', + abbr: 'n', + help: 'Name to be used for the generated constant.' + ); + + parser.addOption( + 'part-of', + abbr: 'p', + help: 'Library name to add a dart \'part of\' clause for.' + ); + + parser.addOption( + 'header', + abbr: 'd', + help: 'File whose contents are to be prepended to the beginning of ' + 'the generated Dart file; this can be used for a license comment.' + ); + + parser.addFlag( + 'codegen_comment', + abbr: 'c', + defaultsTo: true, + help: 'Whether to include the following comment after the header:\n' + '$kCodegenComment' + ); + + final ArgResults argResults = parser.parse(args); + + if (argResults['help'] || + !argResults.wasParsed('output') || + !argResults.wasParsed('asset-name') || + argResults.rest.isEmpty) { + printUsage(parser); + return; + } + + final List frames = []; + for (String filePath in argResults.rest) { + final FrameData data = interpretSvg(filePath); + frames.add(data); + } + + final StringBuffer generatedSb = new StringBuffer(); + + if (argResults.wasParsed('header')) { + generatedSb.write(new File(argResults['header']).readAsStringSync()); + generatedSb.write('\n'); + } + + if (argResults['codegen_comment']) + generatedSb.write(kCodegenComment); + + if (argResults.wasParsed('part-of')) + generatedSb.write('part of ${argResults['part-of']};\n'); + + final Animation animation = new Animation.fromFrameData(frames); + generatedSb.write(animation.toDart('_AnimatedIconData', argResults['asset-name'])); + + final File outFile = new File(argResults['output']); + outFile.writeAsStringSync(generatedSb.toString()); +} + +void printUsage(ArgParser parser) { + print('Usage: vitool --asset-name= --output= '); + print('\nExample: vitool --asset-name=_\$menu_arrow --output=lib/data/menu_arrow.g.dart assets/svg/menu_arrow/*.svg\n'); + print(parser.usage); +} diff --git a/dev/tools/vitool/lib/vitool.dart b/dev/tools/vitool/lib/vitool.dart new file mode 100644 index 0000000000..7134382843 --- /dev/null +++ b/dev/tools/vitool/lib/vitool.dart @@ -0,0 +1,560 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; +import 'dart:math'; + +import 'package:collection/collection.dart'; +import 'package:meta/meta.dart'; +import 'package:vector_math/vector_math_64.dart'; +import 'package:xml/xml.dart' as xml show parse; +import 'package:xml/xml.dart' hide parse; + +// String to use for a single indentation. +const String kIndent = ' '; + +/// Represents an animation, and provides logic to generate dart code for it. +class Animation { + const Animation(this.size, this.paths); + + factory Animation.fromFrameData(List frames) { + _validateFramesData(frames); + final Point size = frames[0].size; + final List paths = []; + for (int i = 0; i < frames[0].paths.length; i += 1) { + paths.add(new PathAnimation.fromFrameData(frames, i)); + } + return new Animation(size, paths); + } + + /// The size of the animation (width, height) in pixels. + final Point size; + + /// List of paths in the animation. + final List paths; + + static void _validateFramesData(List frames) { + final Point size = frames[0].size; + final int numPaths = frames[0].paths.length; + for (int i = 0; i < frames.length; i += 1) { + final FrameData frame = frames[i]; + if (size != frame.size) + throw new Exception( + 'All animation frames must have the same size,\n' + 'first frame size was: (${size.x}, ${size.y})\n' + 'frame $i size was: (${frame.size.x}, ${frame.size.y})' + ); + if (numPaths != frame.paths.length) + throw new Exception( + 'All animation frames must have the same number of paths,\n' + 'first frame has $numPaths paths\n' + 'frame $i has ${frame.paths.length} paths' + ); + } + } + + String toDart(String className, String varName) { + final StringBuffer sb = new StringBuffer(); + sb.write('const $className $varName = const $className(\n'); + sb.write('${kIndent}const Size(${size.x}, ${size.y}),\n'); + sb.write('${kIndent}const <_PathFrames>[\n'); + for (PathAnimation path in paths) + sb.write(path.toDart()); + sb.write('$kIndent],\n'); + sb.write(');'); + return sb.toString(); + } +} + +/// Represents the animation of a single path. +class PathAnimation { + const PathAnimation(this.commands, {@required this.opacities}); + + factory PathAnimation.fromFrameData(List frames, int pathIdx) { + if (frames.isEmpty) + return const PathAnimation(const [], opacities: const []); + + final List commands = []; + for (int commandIdx = 0; commandIdx < frames[0].paths[pathIdx].commands.length; commandIdx += 1) { + final int numPointsInCommand = frames[0].paths[pathIdx].commands[commandIdx].points.length; + final List>> points = new List>>(numPointsInCommand); + for (int j = 0; j < numPointsInCommand; j += 1) + points[j] = >[]; + final String commandType = frames[0].paths[pathIdx].commands[commandIdx].type; + for (int i = 0; i < frames.length; i += 1) { + final FrameData frame = frames[i]; + final String currentCommandType = frame.paths[pathIdx].commands[commandIdx].type; + if (commandType != currentCommandType) + throw new Exception( + 'Paths must be built from the same commands in all frames' + 'command $commandIdx at frame 0 was of type \'$commandType\'' + 'command $commandIdx at frame $i was of type \'$currentCommandType\'' + ); + for (int j = 0; j < numPointsInCommand; j += 1) + points[j].add(frame.paths[pathIdx].commands[commandIdx].points[j]); + } + commands.add(new PathCommandAnimation(commandType, points)); + } + + final List opacities = + frames.map((FrameData d) => d.paths[pathIdx].opacity).toList(); + + return new PathAnimation(commands, opacities: opacities); + } + + /// List of commands for drawing the path. + final List commands; + /// The path opacity for each animation frame. + final List opacities; + + @override + String toString() { + return 'PathAnimation(commands: $commands, opacities: $opacities)'; + } + + String toDart() { + final StringBuffer sb = new StringBuffer(); + sb.write('${kIndent * 2}const _PathFrames(\n'); + sb.write('${kIndent * 3}opacities: const [\n'); + for (double opacity in opacities) + sb.write('${kIndent * 4}$opacity,\n'); + sb.write('${kIndent * 3}],\n'); + sb.write('${kIndent * 3}commands: const <_PathCommand>[\n'); + for (PathCommandAnimation command in commands) + sb.write(command.toDart()); + sb.write('${kIndent * 3}],\n'); + sb.write('${kIndent * 2}),\n'); + return sb.toString(); + } +} + +/// Represents the animation of a single path command. +class PathCommandAnimation { + const PathCommandAnimation(this.type, this.points); + + /// The command type. + final String type; + + /// A matrix with the command's points in different frames. + /// + /// points[i][j] is the i-th point of the command at frame j. + final List>> points; + + @override + String toString() { + return 'PathCommandAnimation(type: $type, points: $points)'; + } + + String toDart() { + String dartCommandClass; + switch (type) { + case 'M': + dartCommandClass = '_PathMoveTo'; + break; + case 'C': + dartCommandClass = '_PathCubicTo'; + break; + case 'L': + dartCommandClass = '_PathLineTo'; + break; + case 'Z': + dartCommandClass = '_PathClose'; + break; + default: + throw new Exception('unsupported path command: $type'); + } + final StringBuffer sb = new StringBuffer(); + sb.write('${kIndent * 4}const $dartCommandClass(\n'); + for (List> pointFrames in points) { + sb.write('${kIndent * 5}const [\n'); + for (Point point in pointFrames) + sb.write('${kIndent * 6}const Offset(${point.x}, ${point.y}),\n'); + sb.write('${kIndent * 5}],\n'); + } + sb.write('${kIndent * 4}),\n'); + return sb.toString(); + } +} + +/// Interprets some subset of an SVG file. +/// +/// Recursively goes over the SVG tree, applying transforms and opacities, +/// and build a FrameData which is a flat representation of the paths in the SVG +/// file, after applying transformations and converting relative coordinates to +/// absolute. +/// +/// This does not support the SVG specification, but is just built to +/// support SVG files exported by a specific tool the motion design team is +/// using. +FrameData interpretSvg(String svgFilePath) { + final File file = new File(svgFilePath); + final String fileData = file.readAsStringSync(); + final XmlElement svgElement = _extractSvgElement(xml.parse(fileData)); + final double width = parsePixels(_extractAttr(svgElement, 'width')).toDouble(); + final double height = parsePixels(_extractAttr(svgElement, 'height')).toDouble(); + + final List paths = + _interpretSvgGroup(svgElement.children, new _Transform()); + return new FrameData(new Point(width, height), paths); +} + +List _interpretSvgGroup(List children, _Transform transform) { + final List paths = []; + for (XmlNode node in children) { + if (node.nodeType != XmlNodeType.ELEMENT) + continue; + final XmlElement element = node; + + if (element.name.local == 'path') { + paths.add(SvgPath.fromElement(element).applyTransform(transform)); + } + + if (element.name.local == 'g') { + double opacity = transform.opacity; + if (_hasAttr(element, 'opacity')) + opacity *= double.parse(_extractAttr(element, 'opacity')); + + Matrix3 transformMatrix = transform.transformMatrix; + if (_hasAttr(element, 'transform')) + transformMatrix = transformMatrix.multiplied( + _parseSvgTransform(_extractAttr(element, 'transform'))); + + final _Transform subtreeTransform = new _Transform( + transformMatrix: transformMatrix, + opacity: opacity + ); + paths.addAll(_interpretSvgGroup(element.children, subtreeTransform)); + } + } + return paths; +} + +// Given a points list in the form e.g: "25.0, 1.0 12.0, 12.0 23.0, 9.0" matches +// the coordinated of the first point and the rest of the string, for the +// example above: +// group 1 will match "25.0" +// group 2 will match "1.0" +// group 3 will match "12.0, 12.0 23.0, 9.0" +// +// Commas are optional. +final RegExp _pointMatcher = new RegExp(r'^ *([\-\.0-9]+) *,? *([\-\.0-9]+)(.*)'); + +/// Parse a string with a list of points, e.g: +/// '25.0, 1.0 12.0, 12.0 23.0, 9.0' will be parsed to: +/// [Point(25.0, 1.0), Point(12.0, 12.0), Point(23.0, 9.0)]. +/// +/// Commas are optional. +List> parsePoints(String points) { + String unParsed = points; + final List> result = >[]; + while (unParsed.isNotEmpty && _pointMatcher.hasMatch(unParsed)) { + final Match m = _pointMatcher.firstMatch(unParsed); + result.add(new Point( + double.parse(m.group(1)), + double.parse(m.group(2)) + )); + unParsed = m.group(3); + } + return result; +} + +/// Data for a single animation frame. +class FrameData { + const FrameData(this.size, this.paths); + + final Point size; + final List paths; + + @override + bool operator ==(Object other){ + if (runtimeType != other.runtimeType) + return false; + final FrameData typedOther = other; + return size == typedOther.size + && const ListEquality().equals(paths, typedOther.paths); + } + + @override + int get hashCode => size.hashCode ^ paths.hashCode; + + @override + String toString() { + return 'FrameData(size: $size, paths: $paths)'; + } +} + +/// Represents an SVG path element. +class SvgPath { + const SvgPath(this.id, this.commands, {this.opacity = 1.0}); + + final String id; + final List commands; + final double opacity; + + static final String _pathCommandAtom = ' *([a-zA-Z]) *([\-\.0-9 ,]*)'; + static final RegExp _pathCommandValidator = new RegExp('^($_pathCommandAtom)*\$'); + static final RegExp _pathCommandMatcher = new RegExp(_pathCommandAtom); + + static SvgPath fromElement(XmlElement pathElement) { + assert(pathElement.name.local == 'path'); + final String id = _extractAttr(pathElement, 'id'); + final String dAttr = _extractAttr(pathElement, 'd'); + final List commands = []; + final SvgPathCommandBuilder commandsBuilder = new SvgPathCommandBuilder(); + if (!_pathCommandValidator.hasMatch(dAttr)) + throw new Exception('illegal or unsupported path d expression: $dAttr'); + for (Match match in _pathCommandMatcher.allMatches(dAttr)) { + final String commandType = match.group(1); + final String pointStr = match.group(2); + commands.add(commandsBuilder.build(commandType, parsePoints(pointStr))); + } + return new SvgPath(id, commands); + } + + SvgPath applyTransform(_Transform transform) { + final List transformedCommands = + commands.map((SvgPathCommand c) => c.applyTransform(transform)).toList(); + return new SvgPath(id, transformedCommands, opacity: opacity * transform.opacity); + } + + @override + bool operator ==(Object other) { + if (runtimeType != other.runtimeType) + return false; + final SvgPath typedOther = other; + return id == typedOther.id + && opacity == typedOther.opacity + && const ListEquality().equals(commands, typedOther.commands); + } + + @override + int get hashCode => id.hashCode ^ commands.hashCode ^ opacity.hashCode; + + @override + String toString() { + return 'SvgPath(id: $id, opacity: $opacity, commands: $commands)'; + } + +} + +/// Represents a single SVG path command from an SVG d element. +/// +/// This class normalizes all the 'd' commands into a single type, that has +/// a command type and a list of points. +/// +/// Some examples of how d commands translated to SvgPathCommand: +/// * "M 0.0, 1.0" => SvgPathCommand('M', [Point(0.0, 1.0)]) +/// * "Z" => SvgPathCommand('Z', []) +/// * "C 1.0, 1.0 2.0, 2.0 3.0, 3.0" SvgPathCommand('C', [Point(1.0, 1.0), +/// Point(2.0, 2.0), Point(3.0, 3.0)]) +class SvgPathCommand { + const SvgPathCommand(this.type, this.points); + + /// The command type. + final String type; + + /// List of points used by this command. + final List> points; + + SvgPathCommand applyTransform(_Transform transform) { + final List> transformedPoints = + _vector3ArrayToPoints( + transform.transformMatrix.applyToVector3Array( + _pointsToVector3Array(points) + ) + ); + return new SvgPathCommand(type, transformedPoints); + } + + @override + bool operator ==(Object other) { + if (runtimeType != other.runtimeType) + return false; + final SvgPathCommand typedOther = other; + return type == typedOther.type + && const ListEquality>().equals(points, typedOther.points); + } + + @override + int get hashCode => type.hashCode ^ points.hashCode; + + @override + String toString() { + return 'SvgPathCommand(type: $type, points: $points)'; + } +} + +class SvgPathCommandBuilder { + static const Map kRelativeCommands = const { + 'c': null, + 'l': null, + 'm': null, + 't': null, + 's': null, + }; + + Point lastPoint = const Point(0.0, 0.0); + Point subPathStartPoint = const Point(0.0, 0.0); + + SvgPathCommand build(String type, List> points) { + List> absPoints = points; + if (_isRelativeCommand(type)) { + absPoints = points.map((Point p) => p + lastPoint).toList(); + } + + if (type == 'M' || type == 'm') + subPathStartPoint = absPoints.last; + + if (type == 'Z' || type == 'z') + lastPoint = subPathStartPoint; + else + lastPoint = absPoints.last; + + return new SvgPathCommand(type.toUpperCase(), absPoints); + } + + static bool _isRelativeCommand(String type) { + return kRelativeCommands.containsKey(type); + } +} + +List _pointsToVector3Array(List> points) { + final List result = new List(points.length * 3); + for (int i = 0; i < points.length; i += 1) { + result[i * 3] = points[i].x; + result[i * 3 + 1] = points[i].y; + result[i * 3 + 2] = 1.0; + } + return result; +} + +List> _vector3ArrayToPoints(List vector) { + final int numPoints = (vector.length / 3).floor(); + final List> points = new List>(numPoints); + for (int i = 0; i < numPoints; i += 1) { + points[i] = new Point(vector[i*3], vector[i*3 + 1]); + } + return points; +} + +/// Represents a transformation to apply on an SVG subtree. +/// +/// This includes more transforms than the ones described by the SVG transform +/// attribute, e.g opacity. +class _Transform { + + /// Constructs a new _Transform, default arguments create a no-op transform. + _Transform({Matrix3 transformMatrix, this.opacity = 1.0}) : + this.transformMatrix = transformMatrix ?? new Matrix3.identity(); + + final Matrix3 transformMatrix; + final double opacity; + + _Transform applyTransform(_Transform transform) { + return new _Transform( + transformMatrix: transform.transformMatrix.multiplied(transformMatrix), + opacity: transform.opacity * opacity, + ); + } +} + + +final String _transformCommandAtom = ' *([^(]+)\\(([^)]*)\\)'; +final RegExp _transformValidator = new RegExp('^($_transformCommandAtom)*\$'); +final RegExp _transformCommand = new RegExp(_transformCommandAtom); + +Matrix3 _parseSvgTransform(String transform){ + if (!_transformValidator.hasMatch(transform)) + throw new Exception('illegal or unsupported transform: $transform'); + final Iterable matches =_transformCommand.allMatches(transform).toList().reversed; + Matrix3 result = new Matrix3.identity(); + for (Match m in matches) { + final String command = m.group(1); + final String params = m.group(2); + if (command == 'translate') { + result = _parseSvgTranslate(params).multiplied(result); + continue; + } + if (command == 'scale') { + result = _parseSvgScale(params).multiplied(result); + continue; + } + if (command == 'rotate') { + result = _parseSvgRotate(params).multiplied(result); + continue; + } + throw new Exception('unimplemented transform: $command'); + } + return result; +} + +final RegExp _valueSeparator = new RegExp('( *, *| +)'); + +Matrix3 _parseSvgTranslate(String paramsStr) { + final List params = paramsStr.split(_valueSeparator); + assert(params.isNotEmpty); + assert(params.length <= 2); + final double x = double.parse(params[0]); + final double y = params.length < 2 ? 0 : double.parse(params[1]); + return _matrix(1.0, 0.0, 0.0, 1.0, x, y); +} + +Matrix3 _parseSvgScale(String paramsStr) { + final List params = paramsStr.split(_valueSeparator); + assert(params.isNotEmpty); + assert(params.length <= 2); + final double x = double.parse(params[0]); + final double y = params.length < 2 ? 0 : double.parse(params[1]); + return _matrix(x, 0.0, 0.0, y, 0.0, 0.0); +} + +Matrix3 _parseSvgRotate(String paramsStr) { + final List params = paramsStr.split(_valueSeparator); + assert(params.length == 1); + final double a = radians(double.parse(params[0])); + return _matrix(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0); +} + +Matrix3 _matrix(double a, double b, double c, double d, double e, double f) { + return new Matrix3(a, b, 0.0, c, d, 0.0, e, f, 1.0); +} + +// Matches a pixels expression e.g "14px". +// First group is just the number. +final RegExp _pixelsExp = new RegExp('^([0-9]+)px\$'); + +/// Parses a pixel expression, e.g "14px", and returns the number. +/// Throws an [ArgumentError] if the given string doesn't match the pattern. +int parsePixels(String pixels) { + if (!_pixelsExp.hasMatch(pixels)) + throw new ArgumentError( + 'illegal pixels expression: \'$pixels\'' + ' (the tool currently only support pixel units).'); + return int.parse(_pixelsExp.firstMatch(pixels).group(1)); +} + +String _extractAttr(XmlElement element, String name) { + try { + return element.attributes.singleWhere((XmlAttribute x) => x.name.local == name) + .value; + } catch (e) { + throw new ArgumentError( + 'Can\'t find a single \'$name\' attributes in ${element.name}, ' + 'attributes were: ${element.attributes}' + ); + } +} + +bool _hasAttr(XmlElement element, String name) { + return element.attributes.where((XmlAttribute a) => a.name.local == name).isNotEmpty; +} + +XmlElement _extractSvgElement(XmlDocument document) { + return document.children.singleWhere( + (XmlNode node) => node.nodeType == XmlNodeType.ELEMENT && + _asElement(node).name.local == 'svg' + ); +} + +XmlElement _asElement(XmlNode node) => node; diff --git a/dev/tools/vitool/pubspec.yaml b/dev/tools/vitool/pubspec.yaml new file mode 100644 index 0000000000..824c6b4615 --- /dev/null +++ b/dev/tools/vitool/pubspec.yaml @@ -0,0 +1,54 @@ +name: vitool +description: A tool for generating Dart vector animation code from SVG sequences. +version: 0.0.1 +homepage: https://flutter.io +author: Flutter Authors + +environment: + sdk: '>=1.20.1 <2.0.0' + +dependencies: + args: 0.13.7 + vector_math: 2.0.5 + xml: 2.6.0 + +dev_dependencies: + test: 0.12.26 + + async: 1.13.3 # TRANSITIVE DEPENDENCY + barback: 0.15.2+13 # TRANSITIVE DEPENDENCY + boolean_selector: 1.0.2 # TRANSITIVE DEPENDENCY + charcode: 1.1.1 # TRANSITIVE DEPENDENCY + collection: 1.14.3 # TRANSITIVE DEPENDENCY + convert: 2.0.1 # TRANSITIVE DEPENDENCY + crypto: 2.0.2+1 # TRANSITIVE DEPENDENCY + glob: 1.1.5 # TRANSITIVE DEPENDENCY + http: 0.11.3+14 # TRANSITIVE DEPENDENCY + http_multi_server: 2.0.4 # TRANSITIVE DEPENDENCY + http_parser: 3.1.1 # TRANSITIVE DEPENDENCY + io: 0.3.1 # TRANSITIVE DEPENDENCY + js: 0.6.1 # TRANSITIVE DEPENDENCY + matcher: 0.12.1+4 # TRANSITIVE DEPENDENCY + meta: 1.1.1 # TRANSITIVE DEPENDENCY + mime: 0.9.5 # TRANSITIVE DEPENDENCY + node_preamble: 1.4.0 # TRANSITIVE DEPENDENCY + package_config: 1.0.3 # TRANSITIVE DEPENDENCY + package_resolver: 1.0.2 # TRANSITIVE DEPENDENCY + path: 1.5.1 # TRANSITIVE DEPENDENCY + petitparser: 1.6.1 # TRANSITIVE DEPENDENCY + pool: 1.3.3 # TRANSITIVE DEPENDENCY + pub_semver: 1.3.2 # TRANSITIVE DEPENDENCY + shelf: 0.7.1 # TRANSITIVE DEPENDENCY + shelf_packages_handler: 1.0.3 # TRANSITIVE DEPENDENCY + shelf_static: 0.2.6 # TRANSITIVE DEPENDENCY + shelf_web_socket: 0.2.2 # TRANSITIVE DEPENDENCY + source_map_stack_trace: 1.1.4 # TRANSITIVE DEPENDENCY + source_maps: 0.10.4 # TRANSITIVE DEPENDENCY + source_span: 1.4.0 # TRANSITIVE DEPENDENCY + stack_trace: 1.9.1 # TRANSITIVE DEPENDENCY + stream_channel: 1.6.2 # TRANSITIVE DEPENDENCY + string_scanner: 1.0.2 # TRANSITIVE DEPENDENCY + term_glyph: 1.0.0 # TRANSITIVE DEPENDENCY + typed_data: 1.1.4 # TRANSITIVE DEPENDENCY + web_socket_channel: 1.0.6 # TRANSITIVE DEPENDENCY + yaml: 2.1.13 # TRANSITIVE DEPENDENCY diff --git a/dev/tools/vitool/test/vitool_test.dart b/dev/tools/vitool/test/vitool_test.dart new file mode 100644 index 0000000000..b915ca92d2 --- /dev/null +++ b/dev/tools/vitool/test/vitool_test.dart @@ -0,0 +1,698 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:math'; + +import 'package:collection/collection.dart'; +import 'package:vitool/vitool.dart'; +import 'package:test/test.dart'; +import 'package:path/path.dart' as path; + +const String kPackagePath = '..'; + +void main() { + + test('parsePixels', () { + expect(parsePixels('23px'), 23); + expect(parsePixels('9px'), 9); + expect(() { parsePixels('9pt'); }, throwsA(const isInstanceOf())); + }); + + test('parsePoints', () { + expect(parsePoints('1.0, 2.0'), + const >[const Point(1.0, 2.0)] + ); + expect(parsePoints('12.0, 34.0 5.0, 6.6'), + const >[ + const Point(12.0, 34.0), + const Point(5.0, 6.6), + ] + ); + expect(parsePoints('12.0 34.0 5.0 6.6'), + const >[ + const Point(12.0, 34.0), + const Point(5.0, 6.6), + ] + ); + }); + + group('parseSvg', () { + test('empty SVGs', () { + interpretSvg(testAsset('empty_svg_1_48x48.svg')); + interpretSvg(testAsset('empty_svg_2_100x50.svg')); + }); + + test('illegal SVGs', () { + expect( + () { interpretSvg(testAsset('illegal_svg_multiple_roots.svg')); }, + throwsA(anything) + ); + }); + + test('SVG size', () { + expect( + interpretSvg(testAsset('empty_svg_1_48x48.svg')).size, + const Point(48.0, 48.0) + ); + + expect( + interpretSvg(testAsset('empty_svg_2_100x50.svg')).size, + const Point(100.0, 50.0) + ); + }); + + test('horizontal bar', () { + final FrameData frameData = interpretSvg(testAsset('horizontal_bar.svg')); + expect(frameData.paths, [ + const SvgPath('path_1', const[ + const SvgPathCommand('M', const >[const Point(0.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 29.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 29.0)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + + test('leading space path command', () { + interpretSvg(testAsset('leading_space_path_command.svg')); + }); + + test('SVG illegal path', () { + expect( + () { interpretSvg(testAsset('illegal_path.svg')); }, + throwsA(anything) + ); + }); + + + test('SVG group', () { + final FrameData frameData = interpretSvg(testAsset('bars_group.svg')); + expect(frameData.paths, const [ + const SvgPath('path_1', const[ + const SvgPathCommand('M', const >[const Point(0.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 29.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 29.0)]), + const SvgPathCommand('Z', const >[]), + ]), + const SvgPath('path_2', const[ + const SvgPathCommand('M', const >[const Point(0.0, 34.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 34.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 44.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 44.0)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + + test('SVG group translate', () { + final FrameData frameData = interpretSvg(testAsset('bar_group_translate.svg')); + expect(frameData.paths, const [ + const SvgPath('path_1', const[ + const SvgPathCommand('M', const >[const Point(0.0, 34.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 34.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 44.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 44.0)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + + test('SVG group scale', () { + final FrameData frameData = interpretSvg(testAsset('bar_group_scale.svg')); + expect(frameData.paths, const [ + const SvgPath( + 'path_1', const[ + const SvgPathCommand('M', const >[const Point(0.0, 9.5)]), + const SvgPathCommand('L', const >[const Point(24.0, 9.5)]), + const SvgPathCommand('L', const >[const Point(24.0, 14.5)]), + const SvgPathCommand('L', const >[const Point(0.0, 14.5)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + + test('SVG group rotate scale', () { + final FrameData frameData = interpretSvg(testAsset('bar_group_rotate_scale.svg')); + expect(frameData.paths, const [ + const PathMatcher( + const SvgPath( + 'path_1', const[ + const SvgPathCommand('L', const >[const Point(29.0, 0.0)]), + const SvgPathCommand('L', const >[const Point(29.0, 48.0)]), + const SvgPathCommand('L', const >[const Point(19.0, 48.0)]), + const SvgPathCommand('M', const >[const Point(19.0, 0.0)]), + const SvgPathCommand('Z', const >[]), + ]), + margin: 0.000000001 + ) + ]); + }); + + test('SVG illegal transform', () { + expect( + () { interpretSvg(testAsset('illegal_transform.svg')); }, + throwsA(anything) + ); + }); + + test('SVG group opacity', () { + final FrameData frameData = interpretSvg(testAsset('bar_group_opacity.svg')); + expect(frameData.paths, const [ + const SvgPath( + 'path_1', + const[ + const SvgPathCommand('M', const >[const Point(0.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 29.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 29.0)]), + const SvgPathCommand('Z', const >[]), + ], + opacity: 0.5, + ), + ]); + }); + + test('horizontal bar relative', () { + // This asset uses the relative 'l' command instead of 'L'. + final FrameData frameData = interpretSvg(testAsset('horizontal_bar_relative.svg')); + expect(frameData.paths, const [ + const SvgPath( + 'path_1', const[ + const SvgPathCommand('M', const >[const Point(0.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 19.0)]), + const SvgPathCommand('L', const >[const Point(48.0, 29.0)]), + const SvgPathCommand('L', const >[const Point(0.0, 29.0)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + + test('close in middle of path', () { + // This asset uses the relative 'l' command instead of 'L'. + final FrameData frameData = interpretSvg(testAsset('close_path_in_middle.svg')); + expect(frameData.paths, const [ + const SvgPath( + 'path_1', const[ + const SvgPathCommand('M', const >[const Point(50.0, 50.0)]), + const SvgPathCommand('L', const >[const Point(60.0, 50.0)]), + const SvgPathCommand('L', const >[const Point(60.0, 60.0)]), + const SvgPathCommand('Z', const >[]), + const SvgPathCommand('L', const >[const Point(50.0, 40.0)]), + const SvgPathCommand('L', const >[const Point(40.0, 40.0)]), + const SvgPathCommand('Z', const >[]), + ]), + ]); + }); + }); + + group('create PathAnimation', () { + test('single path', () { + final List frameData = const [ + const FrameData( + const Point(10.0, 10.0), + const [ + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(0.0, 0.0)]), + const SvgPathCommand('L', const >[const Point(10.0, 10.0)]), + ], + ), + ], + ), + ]; + expect(new PathAnimation.fromFrameData(frameData, 0), + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[const Point(0.0, 0.0)], + ]), + const PathCommandAnimation('L', const >>[ + const >[const Point(10.0, 10.0)], + ]), + ], + opacities: const [1.0] + )) + ); + }); + + test('multiple paths', () { + final List frameData = const [ + const FrameData( + const Point(10.0, 10.0), + const [ + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(0.0, 0.0)]), + ], + ), + const SvgPath( + 'path_2', + const [ + const SvgPathCommand('M', const >[const Point(5.0, 6.0)]), + ], + ), + ], + ), + ]; + expect(new PathAnimation.fromFrameData(frameData, 0), + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[const Point(0.0, 0.0)], + ]) + ], + opacities: const [1.0] + )) + ); + + expect(new PathAnimation.fromFrameData(frameData, 1), + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[const Point(5.0, 6.0)], + ]) + ], + opacities: const [1.0] + )) + ); + }); + + test('multiple frames', () { + final List frameData = const [ + const FrameData( + const Point(10.0, 10.0), + const [ + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(0.0, 0.0)]) + ], + opacity: 0.5, + ), + ], + ), + const FrameData( + const Point(10.0, 10.0), + const [ + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(10.0, 10.0)]) + ], + ), + ], + ), + ]; + expect(new PathAnimation.fromFrameData(frameData, 0), + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[ + const Point(0.0, 0.0), + const Point(10.0, 10.0), + ], + ]), + ], + opacities: const [0.5, 1.0] + )) + ); + }); + }); + + group('create Animation', () { + test('multiple paths', () { + final List frameData = const [ + const FrameData( + const Point(10.0, 10.0), + const [ + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(0.0, 0.0)]), + ], + ), + const SvgPath( + 'path_1', + const [ + const SvgPathCommand('M', const >[const Point(5.0, 6.0)]), + ], + ), + ], + ), + ]; + final Animation animation = new Animation.fromFrameData(frameData); + expect(animation.paths[0], + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[const Point(0.0, 0.0)], + ]) + ], + opacities: const [1.0] + )) + ); + + expect(animation.paths[1], + const PathAnimationMatcher(const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[const Point(5.0, 6.0)], + ]) + ], + opacities: const [1.0] + )) + ); + + expect(animation.size, const Point(10.0, 10.0)); + }); + }); + + group('toDart', () { + test('_PathMoveTo', () { + final PathCommandAnimation command = const PathCommandAnimation( + 'M', + const >>[ + const >[ + const Point(1.0, 2.0), + const Point(3.0, 4.0), + ], + ], + ); + + expect(command.toDart(), + ' const _PathMoveTo(\n' + ' const [\n' + ' const Offset(1.0, 2.0),\n' + ' const Offset(3.0, 4.0),\n' + ' ],\n' + ' ),\n' + + ); + }); + + test('_PathLineTo', () { + final PathCommandAnimation command = const PathCommandAnimation( + 'L', + const >>[ + const >[ + const Point(1.0, 2.0), + const Point(3.0, 4.0), + ], + ], + ); + + expect(command.toDart(), + ' const _PathLineTo(\n' + ' const [\n' + ' const Offset(1.0, 2.0),\n' + ' const Offset(3.0, 4.0),\n' + ' ],\n' + ' ),\n' + + ); + }); + + test('_PathCubicTo', () { + final PathCommandAnimation command = const PathCommandAnimation( + 'C', + const >>[ + const >[ + const Point(16.0, 24.0), + const Point(16.0, 10.0), + ], + const >[ + const Point(16.0, 25.0), + const Point(16.0, 11.0), + ], + const >[ + const Point(40.0, 40.0), + const Point(40.0, 40.0), + ], + ], + ); + + expect(command.toDart(), + ' const _PathCubicTo(\n' + ' const [\n' + ' const Offset(16.0, 24.0),\n' + ' const Offset(16.0, 10.0),\n' + ' ],\n' + ' const [\n' + ' const Offset(16.0, 25.0),\n' + ' const Offset(16.0, 11.0),\n' + ' ],\n' + ' const [\n' + ' const Offset(40.0, 40.0),\n' + ' const Offset(40.0, 40.0),\n' + ' ],\n' + ' ),\n' + + ); + }); + + test('_PathClose', () { + final PathCommandAnimation command = const PathCommandAnimation( + 'Z', + const >>[], + ); + + expect(command.toDart(), + ' const _PathClose(\n' + ' ),\n' + + ); + }); + + test('Unsupported path command', () { + final PathCommandAnimation command = const PathCommandAnimation( + 'h', + const >>[], + ); + + expect( + () { command.toDart(); }, + throwsA(anything) + ); + }); + + test('_PathFrames', () { + final PathAnimation pathAnimation = const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[ + const Point(0.0, 0.0), + const Point(10.0, 10.0), + ], + ]), + const PathCommandAnimation('L', const >>[ + const >[ + const Point(48.0, 10.0), + const Point(0.0, 0.0), + ], + ]), + ], + opacities: const [0.5, 1.0] + ); + + expect(pathAnimation.toDart(), + ' const _PathFrames(\n' + ' opacities: const [\n' + ' 0.5,\n' + ' 1.0,\n' + ' ],\n' + ' commands: const <_PathCommand>[\n' + ' const _PathMoveTo(\n' + ' const [\n' + ' const Offset(0.0, 0.0),\n' + ' const Offset(10.0, 10.0),\n' + ' ],\n' + ' ),\n' + ' const _PathLineTo(\n' + ' const [\n' + ' const Offset(48.0, 10.0),\n' + ' const Offset(0.0, 0.0),\n' + ' ],\n' + ' ),\n' + ' ],\n' + ' ),\n' + ); + }); + + test('Animation', () { + final Animation animation = const Animation( + const Point(48.0, 48.0), + const [ + const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[ + const Point(0.0, 0.0), + const Point(10.0, 10.0), + ], + ]), + const PathCommandAnimation('L', const >>[ + const >[ + const Point(48.0, 10.0), + const Point(0.0, 0.0), + ], + ]), + ], + opacities: const [0.5, 1.0] + ), + + const PathAnimation( + const [ + const PathCommandAnimation('M', const >>[ + const >[ + const Point(0.0, 0.0), + const Point(10.0, 10.0), + ], + ]), + ], + opacities: const [0.5, 1.0] + ), + ]); + + expect(animation.toDart('_AnimatedIconData', '_\$data1'), + 'const _AnimatedIconData _\$data1 = const _AnimatedIconData(\n' + ' const Size(48.0, 48.0),\n' + ' const <_PathFrames>[\n' + ' const _PathFrames(\n' + ' opacities: const [\n' + ' 0.5,\n' + ' 1.0,\n' + ' ],\n' + ' commands: const <_PathCommand>[\n' + ' const _PathMoveTo(\n' + ' const [\n' + ' const Offset(0.0, 0.0),\n' + ' const Offset(10.0, 10.0),\n' + ' ],\n' + ' ),\n' + ' const _PathLineTo(\n' + ' const [\n' + ' const Offset(48.0, 10.0),\n' + ' const Offset(0.0, 0.0),\n' + ' ],\n' + ' ),\n' + ' ],\n' + ' ),\n' + ' const _PathFrames(\n' + ' opacities: const [\n' + ' 0.5,\n' + ' 1.0,\n' + ' ],\n' + ' commands: const <_PathCommand>[\n' + ' const _PathMoveTo(\n' + ' const [\n' + ' const Offset(0.0, 0.0),\n' + ' const Offset(10.0, 10.0),\n' + ' ],\n' + ' ),\n' + ' ],\n' + ' ),\n' + ' ],\n' + ');' + ); + }); + }); +} + +// Matches all path commands' points within an error margin. +class PathMatcher extends Matcher { + const PathMatcher(this.actual, {this.margin = 0.0}); + + final SvgPath actual; + final double margin; + + @override + Description describe(Description description) => description.add('$actual (±$margin)'); + + @override + bool matches(dynamic item, Map matchState) { + if (item == null || actual == null) + return item == actual; + + if (item.runtimeType != actual.runtimeType) + return false; + + final SvgPath other = item; + if (other.id != actual.id || other.opacity != actual.opacity) + return false; + + if (other.commands.length != actual.commands.length) + return false; + + for (int i = 0; i < other.commands.length; i += 1) { + if (!commandsMatch(actual.commands[i], other.commands[i])) + return false; + } + return true; + } + + bool commandsMatch(SvgPathCommand actual, SvgPathCommand other) { + if (other.points.length != actual.points.length) + return false; + + for (int i = 0; i < other.points.length; i += 1) { + if ((other.points[i].x - actual.points[i].x).abs() > margin) + return false; + if ((other.points[i].y - actual.points[i].y).abs() > margin) + return false; + } + return true; + } +} + +class PathAnimationMatcher extends Matcher { + const PathAnimationMatcher(this.expected); + + final PathAnimation expected; + + @override + Description describe(Description description) => description.add('$expected'); + + @override + bool matches(dynamic item, Map matchState) { + if (item == null || expected == null) + return item == expected; + + if (item.runtimeType != expected.runtimeType) + return false; + + final PathAnimation other = item; + + if (!const ListEquality().equals(other.opacities, expected.opacities)) + return false; + + if (other.commands.length != expected.commands.length) + return false; + + for (int i = 0; i < other.commands.length; i += 1) { + if (!commandsMatch(expected.commands[i], other.commands[i])) + return false; + } + return true; + } + + bool commandsMatch(PathCommandAnimation expected, PathCommandAnimation other) { + if (other.points.length != expected.points.length) + return false; + + for (int i = 0; i < other.points.length; i += 1) + if (!const ListEquality>().equals(other.points[i], expected.points[i])) + return false; + + return true; + } +} + +String testAsset(String name) { + return path.join(kPackagePath, 'test_assets', name); +} + diff --git a/dev/tools/vitool/test_assets/bar_group_opacity.svg b/dev/tools/vitool/test_assets/bar_group_opacity.svg new file mode 100644 index 0000000000..03ba8c4670 --- /dev/null +++ b/dev/tools/vitool/test_assets/bar_group_opacity.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/tools/vitool/test_assets/bar_group_rotate_scale.svg b/dev/tools/vitool/test_assets/bar_group_rotate_scale.svg new file mode 100644 index 0000000000..d3bd2ecebd --- /dev/null +++ b/dev/tools/vitool/test_assets/bar_group_rotate_scale.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/tools/vitool/test_assets/bar_group_scale.svg b/dev/tools/vitool/test_assets/bar_group_scale.svg new file mode 100644 index 0000000000..24faab61ad --- /dev/null +++ b/dev/tools/vitool/test_assets/bar_group_scale.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/tools/vitool/test_assets/bar_group_translate.svg b/dev/tools/vitool/test_assets/bar_group_translate.svg new file mode 100644 index 0000000000..b572334b34 --- /dev/null +++ b/dev/tools/vitool/test_assets/bar_group_translate.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/tools/vitool/test_assets/bars_group.svg b/dev/tools/vitool/test_assets/bars_group.svg new file mode 100644 index 0000000000..d09edcc50f --- /dev/null +++ b/dev/tools/vitool/test_assets/bars_group.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dev/tools/vitool/test_assets/close_path_in_middle.svg b/dev/tools/vitool/test_assets/close_path_in_middle.svg new file mode 100644 index 0000000000..5c905786ce --- /dev/null +++ b/dev/tools/vitool/test_assets/close_path_in_middle.svg @@ -0,0 +1,3 @@ + + + diff --git a/dev/tools/vitool/test_assets/empty_svg_1_48x48.svg b/dev/tools/vitool/test_assets/empty_svg_1_48x48.svg new file mode 100644 index 0000000000..3edd7b8662 --- /dev/null +++ b/dev/tools/vitool/test_assets/empty_svg_1_48x48.svg @@ -0,0 +1,2 @@ + + diff --git a/dev/tools/vitool/test_assets/empty_svg_2_100x50.svg b/dev/tools/vitool/test_assets/empty_svg_2_100x50.svg new file mode 100644 index 0000000000..bf94fb283e --- /dev/null +++ b/dev/tools/vitool/test_assets/empty_svg_2_100x50.svg @@ -0,0 +1,8 @@ + + + + diff --git a/dev/tools/vitool/test_assets/horizontal_bar.svg b/dev/tools/vitool/test_assets/horizontal_bar.svg new file mode 100644 index 0000000000..dcdbb4b7c2 --- /dev/null +++ b/dev/tools/vitool/test_assets/horizontal_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/dev/tools/vitool/test_assets/horizontal_bar_relative.svg b/dev/tools/vitool/test_assets/horizontal_bar_relative.svg new file mode 100644 index 0000000000..a8b9b92e1e --- /dev/null +++ b/dev/tools/vitool/test_assets/horizontal_bar_relative.svg @@ -0,0 +1,3 @@ + + + diff --git a/dev/tools/vitool/test_assets/illegal_path.svg b/dev/tools/vitool/test_assets/illegal_path.svg new file mode 100644 index 0000000000..8ab200771c --- /dev/null +++ b/dev/tools/vitool/test_assets/illegal_path.svg @@ -0,0 +1,3 @@ + + + diff --git a/dev/tools/vitool/test_assets/illegal_svg_multiple_roots.svg b/dev/tools/vitool/test_assets/illegal_svg_multiple_roots.svg new file mode 100644 index 0000000000..ec71499194 --- /dev/null +++ b/dev/tools/vitool/test_assets/illegal_svg_multiple_roots.svg @@ -0,0 +1,3 @@ + + + diff --git a/dev/tools/vitool/test_assets/illegal_transform.svg b/dev/tools/vitool/test_assets/illegal_transform.svg new file mode 100644 index 0000000000..a5802fff3b --- /dev/null +++ b/dev/tools/vitool/test_assets/illegal_transform.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dev/tools/vitool/test_assets/leading_space_path_command.svg b/dev/tools/vitool/test_assets/leading_space_path_command.svg new file mode 100644 index 0000000000..2c545428d6 --- /dev/null +++ b/dev/tools/vitool/test_assets/leading_space_path_command.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/flutter/lib/material_animated_icons.dart b/packages/flutter/lib/material_animated_icons.dart new file mode 100644 index 0000000000..2bcecae344 --- /dev/null +++ b/packages/flutter/lib/material_animated_icons.dart @@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Flutter widgets implementing Material Design animated icons. +/// +/// To use, import `package:flutter/material_animated_icons.dart`. +library material_animated_icons; + +import 'dart:math' as math show pi; +import 'dart:ui' as ui show Paint, Path, Canvas; +import 'dart:ui' show lerpDouble; + +import 'package:flutter/material.dart'; +import 'package:meta/meta.dart'; + +// This package is split into multiple parts to enable a private API that is +// testable. + +// Public API. +part 'src/material_animated_icons/animated_icons.dart'; +// Provides a public interface for referring to the private icon +// implementations. +part 'src/material_animated_icons/animated_icons_data.dart'; + +// Animated icons data files. +part 'src/material_animated_icons/data/arrow_menu.g.dart'; +part 'src/material_animated_icons/data/menu_arrow.g.dart'; diff --git a/packages/flutter/lib/src/material_animated_icons/animated_icons.dart b/packages/flutter/lib/src/material_animated_icons/animated_icons.dart new file mode 100644 index 0000000000..7e3bd5fb1f --- /dev/null +++ b/packages/flutter/lib/src/material_animated_icons/animated_icons.dart @@ -0,0 +1,299 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of material_animated_icons; + +// The code for drawing animated icons is kept in a private API, as we are not +// yet ready for exposing a public API for (partial) vector graphics support. +// See: https://github.com/flutter/flutter/issues/1831 for details regarding +// generic vector graphics support in Flutter. + +// Examples can assume: +// AnimationController controller; + +/// Shows an animated icon at a given animation [progress]. +/// +/// The available icons are specified in [AnimatedIcons]. +/// +/// ### Sample code +/// +/// ```dart +/// new AnimatedIcon( +/// icon: AnimatedIcons.menu_arrow, +/// progress: controller, +/// semanticLabel: 'Show menu', +/// ) +/// ``` +/// +class AnimatedIcon extends StatelessWidget { + + /// Creates an AnimatedIcon. + /// + /// The [progress] and [icon] arguments must not be null. + /// The [size] and [color] default to the value given by the current [IconTheme]. + const AnimatedIcon({ + Key key, + @required this.icon, + @required this.progress, + this.color, + this.size, + this.semanticLabel, + this.textDirection, + }) : assert(progress != null), + assert(icon != null); + + /// The animation progress for the animated icon. + /// + /// The value is clamped to be between 0 and 1. + /// + /// This determines the actual frame that is displayed. + final Animation progress; + + /// The color to use when drawing the icon. + /// + /// Defaults to the current [IconTheme] color, if any. + /// + /// The given color will be adjusted by the opacity of the current + /// [IconTheme], if any. + /// + /// In material apps, if there is a [Theme] without any [IconTheme]s + /// specified, icon colors default to white if the theme is dark + /// and black if the theme is light. + /// + /// If no [IconTheme] and no [Theme] is specified, icons will default to black. + /// + /// See [Theme] to set the current theme and [ThemeData.brightness] + /// for setting the current theme's brightness. + final Color color; + + /// The size of the icon in logical pixels. + /// + /// Icons occupy a square with width and height equal to size. + /// + /// Defaults to the current [IconTheme] size. + final double size; + + /// The icon to display. Available icons are listed in [AnimatedIcons]. + final AnimatedIconData icon; + + /// Semantic label for the icon. + /// + /// Announced in accessibility modes (e.g TalkBack/VoiceOver). + /// This label does not show in the UI. + /// + /// See also: + /// + /// * [Semantics.label], which is set to [semanticLabel] in the underlying + /// [Semantics] widget. + final String semanticLabel; + + /// The text direction to use for rendering the icon. + /// + /// If this is null, the ambient [Directionality] is used instead. + /// + /// If the text diection is [TextDirection.rtl], the icon will be mirrored + /// horizontally (e.g back arrow will point right). + final TextDirection textDirection; + + static final _UiPathFactory _pathFactory = () => new ui.Path(); + + @override + Widget build(BuildContext context) { + final _AnimatedIconData iconData = icon; + final IconThemeData iconTheme = IconTheme.of(context); + final double iconSize = size ?? iconTheme.size; + final TextDirection textDirection = this.textDirection ?? Directionality.of(context); + final double iconOpacity = iconTheme.opacity; + Color iconColor = color ?? iconTheme.color; + if (iconOpacity != 1.0) + iconColor = iconColor.withOpacity(iconColor.opacity * iconOpacity); + return new Semantics( + label: semanticLabel, + child: new CustomPaint( + size: new Size(iconSize, iconSize), + painter: new _AnimatedIconPainter( + paths: iconData.paths, + progress: progress, + color: iconColor, + scale: iconSize / iconData.size.width, + shouldMirror: textDirection == TextDirection.rtl && iconData.matchTextDirection, + uiPathFactory: _pathFactory, + ), + ), + ); + } +} + +typedef ui.Path _UiPathFactory(); + +class _AnimatedIconPainter extends CustomPainter { + _AnimatedIconPainter({ + @required this.paths, + @required this.progress, + @required this.color, + @required this.scale, + @required this.shouldMirror, + @required this.uiPathFactory, + }) : super(repaint: progress); + + // This list is assumed to be immutable, changes to the contents of the list + // will not trigger a redraw as shouldRepaint will keep returning false. + final List<_PathFrames> paths; + final Animation progress; + final Color color; + final double scale; + /// If this is true the image will be mirrored horizontally. + final bool shouldMirror; + final _UiPathFactory uiPathFactory; + + @override + void paint(ui.Canvas canvas, Size size) { + // The RenderCustomPaint render object performs canvas.save before invoking + // this and canvas.restore after, so we don't need to do it here. + canvas.scale(scale, scale); + if (shouldMirror) { + canvas.rotate(math.pi); + canvas.translate(-size.width, -size.height); + } + + final double clampedProgress = progress.value.clamp(0.0, 1.0); + for (_PathFrames path in paths) + path.paint(canvas, color, uiPathFactory, clampedProgress); + } + + + @override + bool shouldRepaint(_AnimatedIconPainter oldDelegate) { + return oldDelegate.progress.value != progress.value + || oldDelegate.color != color + // We are comparing the paths list by reference, assuming the list is + // treated as immutable to be more efficient. + || oldDelegate.paths != paths + || oldDelegate.scale != scale + || oldDelegate.uiPathFactory != uiPathFactory; + } + + @override + bool hitTest(Offset position) => null; + + @override + bool shouldRebuildSemantics(CustomPainter oldDelegate) => false; + + @override + SemanticsBuilderCallback get semanticsBuilder => null; +} + +class _PathFrames { + const _PathFrames({ + @required this.commands, + @required this.opacities + }); + + final List<_PathCommand> commands; + final List opacities; + + void paint(ui.Canvas canvas, Color color, _UiPathFactory uiPathFactory, double progress) { + final double opacity = _interpolate(opacities, progress, lerpDouble); + final ui.Paint paint = new ui.Paint() + ..style = PaintingStyle.fill + ..color = color.withOpacity(color.opacity * opacity); + final ui.Path path = uiPathFactory(); + for (_PathCommand command in commands) + command.apply(path, progress); + canvas.drawPath(path, paint); + } +} + +/// Paths are being built by a set of commands e.g moveTo, lineTo, etc... +/// +/// _PathCommand instances represents such a command, and can apply it to +/// a given Path. +abstract class _PathCommand { + const _PathCommand(); + + /// Applies the path command to [path]. + /// + /// For example if the object is a [_PathMoveTo] command it will invoke + /// [Path.moveTo] on [path]. + void apply(ui.Path path, double progress); +} + +class _PathMoveTo extends _PathCommand { + const _PathMoveTo(this.points); + + final List points; + + @override + void apply(Path path, double progress) { + final Offset offset = _interpolate(points, progress, Offset.lerp); + path.moveTo(offset.dx, offset.dy); + } +} + +class _PathCubicTo extends _PathCommand { + const _PathCubicTo(this.controlPoints1, this.controlPoints2, this.targetPoints); + + final List controlPoints2; + final List controlPoints1; + final List targetPoints; + + @override + void apply(Path path, double progress) { + final Offset controlPoint1 = _interpolate(controlPoints1, progress, Offset.lerp); + final Offset controlPoint2 = _interpolate(controlPoints2, progress, Offset.lerp); + final Offset targetPoint = _interpolate(targetPoints, progress, Offset.lerp); + path.cubicTo( + controlPoint1.dx, controlPoint1.dy, + controlPoint2.dx, controlPoint2.dy, + targetPoint.dx, targetPoint.dy + ); + } +} + +// ignore: unused_element +class _PathLineTo extends _PathCommand { + const _PathLineTo(this.points); + + final List points; + + @override + void apply(Path path, double progress) { + final Offset point = _interpolate(points, progress, Offset.lerp); + path.lineTo(point.dx, point.dy); + } +} + +class _PathClose extends _PathCommand { + const _PathClose(); + + @override + void apply(Path path, double progress) { + path.close(); + } +} + +// Interpolates a value given a set of values equally spaced in time. +// +// [interpolator] is the interpolation function used to interpolate between 2 +// points of type T. +// +// This is currently done with linear interpolation between every 2 consecutive +// points. Linear interpolation was smooth enough with the limited set of +// animations we have tested, so we use it for simplicity. If we find this to +// not be smooth enough we can try applying spline instead. +// +// [progress] is expected to be between 0.0 and 1.0. +T _interpolate(List values, double progress, _Interpolator interpolator) { + assert(progress <= 1.0); + assert(progress >= 0.0); + if (values.length == 1) + return values[0]; + final double targetIdx = lerpDouble(0, values.length -1, progress); + final int lowIdx = targetIdx.floor(); + final int highIdx = targetIdx.ceil(); + final double t = targetIdx - lowIdx; + return interpolator(values[lowIdx], values[highIdx], t); +} + +typedef T _Interpolator(T a, T b, double progress); diff --git a/packages/flutter/lib/src/material_animated_icons/animated_icons_data.dart b/packages/flutter/lib/src/material_animated_icons/animated_icons_data.dart new file mode 100644 index 0000000000..02f194e9fc --- /dev/null +++ b/packages/flutter/lib/src/material_animated_icons/animated_icons_data.dart @@ -0,0 +1,54 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file serves as the interface between the public and private APIs for +// animated icons. +// The AnimatedIcons class is public and is used to specify available icons, +// while the _AnimatedIconData interface which used to deliver the icon data is +// kept private. + +part of material_animated_icons; + +/// Identifier for the supported material design animated icons. +/// +/// Use with [AnimatedIcon] class to show specific animated icons. +abstract class AnimatedIcons { + /// The material design arrow to menu icon animation. + static const AnimatedIconData arrow_menu = _$arrow_menu; + + /// The material design menu to arrow icon animation. + static const AnimatedIconData menu_arrow = _$menu_arrow; +} + +/// Vector graphics data for icons used by [AnimatedIcon]. +/// +/// Instances of this class are currently opaque because we have not committed to a specific +/// animated vector graphics format. +/// +/// See also: +/// * [AnimatedIcons], a class that contains constants that implement this interface. +abstract class AnimatedIconData { + /// Abstract const constructor. This constructor enables subclasses to provide + /// const constructors so that they can be used in const expressions. + const AnimatedIconData(); + + /// Whether this icon should be mirrored horizontally when text direction is + /// right-to-left. + /// + /// See also: + /// * [TextDirection], which discusses concerns regarding reading direction + /// in Flutter. + /// * [Directionality], a widget which determines the ambient directionality. + bool get matchTextDirection; +} + +class _AnimatedIconData extends AnimatedIconData { + const _AnimatedIconData(this.size, this.paths, {this.matchTextDirection = false}); + + final Size size; + final List<_PathFrames> paths; + + @override + final bool matchTextDirection; +} diff --git a/packages/flutter/lib/src/material_animated_icons/data/arrow_menu.g.dart b/packages/flutter/lib/src/material_animated_icons/data/arrow_menu.g.dart new file mode 100644 index 0000000000..60a21bed47 --- /dev/null +++ b/packages/flutter/lib/src/material_animated_icons/data/arrow_menu.g.dart @@ -0,0 +1,1027 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// AUTOGENERATED FILE DO NOT EDIT! +// This file was generated by vitool. +part of material_animated_icons; +const _AnimatedIconData _$arrow_menu = const _AnimatedIconData( + const Size(48.0, 48.0), + const <_PathFrames>[ + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(39.94921875, 22.0), + const Offset(39.999299444085175, 22.321134814951655), + const Offset(40.123697128128484, 23.4571221977224), + const Offset(40.127941008338254, 25.772984385261328), + const Offset(39.36673145070893, 29.679631356759792), + const Offset(36.03000494036236, 35.505984938867314), + const Offset(30.483797891740366, 39.621714579092405), + const Offset(23.719442126984134, 41.17597729654657), + const Offset(17.808469902722187, 40.26388356552361), + const Offset(13.571377486425117, 38.15001206462978), + const Offset(10.73996518894534, 35.74540806580379), + const Offset(8.908677157504997, 33.47648684184537), + const Offset(7.746937054898215, 31.506333856475468), + const Offset(7.021336564573183, 29.876779670456198), + const Offset(6.575233382277915, 28.57846974488041), + const Offset(6.306002369153553, 27.58317306758941), + const Offset(6.147597126684428, 26.85785338221681), + const Offset(6.058558318339831, 26.3706514388743), + const Offset(6.013954859968965, 26.093012124442712), + const Offset(6.000028695609693, 26.000194701816614), + const Offset(6.0, 26.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(39.94921875, 22.0), + const Offset(39.999299444085175, 22.321134814951655), + const Offset(40.123697128128484, 23.4571221977224), + const Offset(40.127941008338254, 25.772984385261328), + const Offset(39.36673145070893, 29.679631356759792), + const Offset(36.03000494036236, 35.505984938867314), + const Offset(30.483797891740366, 39.621714579092405), + const Offset(23.719442126984134, 41.17597729654657), + const Offset(17.808469902722187, 40.26388356552361), + const Offset(13.571377486425117, 38.15001206462978), + const Offset(10.73996518894534, 35.74540806580379), + const Offset(8.908677157504997, 33.47648684184537), + const Offset(7.746937054898215, 31.506333856475468), + const Offset(7.021336564573183, 29.876779670456198), + const Offset(6.575233382277915, 28.57846974488041), + const Offset(6.306002369153553, 27.58317306758941), + const Offset(6.147597126684428, 26.85785338221681), + const Offset(6.058558318339831, 26.3706514388743), + const Offset(6.013954859968965, 26.093012124442712), + const Offset(6.000028695609693, 26.000194701816614), + const Offset(6.0, 26.0), + ], + const [ + const Offset(12.562500000000004, 21.999999999999996), + const Offset(12.563028263179644, 21.76974679627851), + const Offset(12.601915221773575, 20.955868783506492), + const Offset(12.859988895862408, 19.29992503795225), + const Offset(13.868967368048864, 16.521093282496043), + const Offset(17.119246052043927, 12.463158561907132), + const Offset(22.085512547276693, 9.843640931525094), + const Offset(27.97135871762438, 9.40112844480027), + const Offset(33.018872763119475, 10.9710702242868), + const Offset(36.55408111158449, 13.438130103560162), + const Offset(38.838028231283474, 16.033718047868426), + const Offset(40.24471329470705, 18.407336125221466), + const Offset(41.07692592252046, 20.434907268146556), + const Offset(41.54755362886814, 22.095337098743826), + const Offset(41.7985009918588, 23.40952601819154), + const Offset(41.921690170757245, 24.41237661448199), + const Offset(41.975185653795926, 25.14085315878499), + const Offset(41.994340767445394, 25.629108510947514), + const Offset(41.999299914344064, 25.906972804802937), + const Offset(41.99999903720365, 25.999805298117412), + const Offset(42.0, 26.0), + ], + const [ + const Offset(12.562500000000004, 21.999999999999996), + const Offset(12.563028263179644, 21.76974679627851), + const Offset(12.601915221773575, 20.955868783506492), + const Offset(12.859988895862408, 19.29992503795225), + const Offset(13.868967368048864, 16.521093282496043), + const Offset(17.119246052043927, 12.463158561907132), + const Offset(22.085512547276693, 9.843640931525094), + const Offset(27.97135871762438, 9.40112844480027), + const Offset(33.018872763119475, 10.9710702242868), + const Offset(36.55408111158449, 13.438130103560162), + const Offset(38.838028231283474, 16.033718047868426), + const Offset(40.24471329470705, 18.407336125221466), + const Offset(41.07692592252046, 20.434907268146556), + const Offset(41.54755362886814, 22.095337098743826), + const Offset(41.7985009918588, 23.40952601819154), + const Offset(41.921690170757245, 24.41237661448199), + const Offset(41.975185653795926, 25.14085315878499), + const Offset(41.994340767445394, 25.629108510947514), + const Offset(41.999299914344064, 25.906972804802937), + const Offset(41.99999903720365, 25.999805298117412), + const Offset(42.0, 26.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(12.562500000000004, 21.999999999999996), + const Offset(12.563028263179644, 21.76974679627851), + const Offset(12.601915221773575, 20.955868783506492), + const Offset(12.859988895862408, 19.29992503795225), + const Offset(13.868967368048864, 16.521093282496043), + const Offset(17.119246052043927, 12.463158561907132), + const Offset(22.085512547276693, 9.843640931525094), + const Offset(27.97135871762438, 9.40112844480027), + const Offset(33.018872763119475, 10.9710702242868), + const Offset(36.55408111158449, 13.438130103560162), + const Offset(38.838028231283474, 16.033718047868426), + const Offset(40.24471329470705, 18.407336125221466), + const Offset(41.07692592252046, 20.434907268146556), + const Offset(41.54755362886814, 22.095337098743826), + const Offset(41.7985009918588, 23.40952601819154), + const Offset(41.921690170757245, 24.41237661448199), + const Offset(41.975185653795926, 25.14085315878499), + const Offset(41.994340767445394, 25.629108510947514), + const Offset(41.999299914344064, 25.906972804802937), + const Offset(41.99999903720365, 25.999805298117412), + const Offset(42.0, 26.0), + ], + const [ + const Offset(12.562500000000004, 25.999999999999996), + const Offset(12.482656306166858, 25.76893925832956), + const Offset(12.239876568700678, 24.939451092644983), + const Offset(11.936115204605002, 23.191770024922107), + const Offset(12.03457162794638, 20.07566671241613), + const Offset(14.027204238592981, 15.000731698561715), + const Offset(18.235691601462104, 10.929402730985391), + const Offset(24.00669715972937, 8.870601601606145), + const Offset(29.46892180503868, 9.127744915172523), + const Offset(33.625033100689926, 10.714038007122415), + const Offset(36.54081321903698, 12.759148887275034), + const Offset(38.511185280577465, 14.802494849349817), + const Offset(39.815969078409935, 16.638858290947915), + const Offset(40.668101748647686, 18.193214036822702), + const Offset(41.21772917473674, 19.451912583754474), + const Offset(41.566980772751144, 20.42813499995029), + const Offset(41.783709535999954, 21.145438675115766), + const Offset(41.9118174384751, 21.629959864025817), + const Offset(41.978620736948194, 21.907026258707322), + const Offset(41.99995577009031, 21.99980529835142), + const Offset(42.0, 22.0), + ], + const [ + const Offset(12.562500000000004, 25.999999999999996), + const Offset(12.482656306166858, 25.76893925832956), + const Offset(12.239876568700678, 24.939451092644983), + const Offset(11.936115204605002, 23.191770024922107), + const Offset(12.03457162794638, 20.07566671241613), + const Offset(14.027204238592981, 15.000731698561715), + const Offset(18.235691601462104, 10.929402730985391), + const Offset(24.00669715972937, 8.870601601606145), + const Offset(29.46892180503868, 9.127744915172523), + const Offset(33.625033100689926, 10.714038007122415), + const Offset(36.54081321903698, 12.759148887275034), + const Offset(38.511185280577465, 14.802494849349817), + const Offset(39.815969078409935, 16.638858290947915), + const Offset(40.668101748647686, 18.193214036822702), + const Offset(41.21772917473674, 19.451912583754474), + const Offset(41.566980772751144, 20.42813499995029), + const Offset(41.783709535999954, 21.145438675115766), + const Offset(41.9118174384751, 21.629959864025817), + const Offset(41.978620736948194, 21.907026258707322), + const Offset(41.99995577009031, 21.99980529835142), + const Offset(42.0, 22.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(12.562500000000004, 25.999999999999996), + const Offset(12.482656306166858, 25.76893925832956), + const Offset(12.239876568700678, 24.939451092644983), + const Offset(11.936115204605002, 23.191770024922107), + const Offset(12.03457162794638, 20.07566671241613), + const Offset(14.027204238592981, 15.000731698561715), + const Offset(18.235691601462104, 10.929402730985391), + const Offset(24.00669715972937, 8.870601601606145), + const Offset(29.46892180503868, 9.127744915172523), + const Offset(33.625033100689926, 10.714038007122415), + const Offset(36.54081321903698, 12.759148887275034), + const Offset(38.511185280577465, 14.802494849349817), + const Offset(39.815969078409935, 16.638858290947915), + const Offset(40.668101748647686, 18.193214036822702), + const Offset(41.21772917473674, 19.451912583754474), + const Offset(41.566980772751144, 20.42813499995029), + const Offset(41.783709535999954, 21.145438675115766), + const Offset(41.9118174384751, 21.629959864025817), + const Offset(41.978620736948194, 21.907026258707322), + const Offset(41.99995577009031, 21.99980529835142), + const Offset(42.0, 22.0), + ], + const [ + const Offset(39.94921875, 26.0), + const Offset(39.91892748707239, 26.320327277002704), + const Offset(39.76165847505559, 27.44070450686089), + const Offset(39.204067317080856, 29.66482937223119), + const Offset(37.532335710606446, 33.23420478667988), + const Offset(32.93796312691141, 38.04355807552189), + const Offset(26.633976945925774, 40.7074763785527), + const Offset(19.754780569089124, 40.645450453352446), + const Offset(14.258518944641395, 38.42055825640933), + const Offset(10.642329475530556, 35.42591996819203), + const Offset(8.442750176698839, 32.47083890521039), + const Offset(7.175149143375414, 29.871645565973722), + const Offset(6.485980210787691, 27.710284879276827), + const Offset(6.141884684352732, 25.97465660853507), + const Offset(5.994461565155852, 24.620856310443347), + const Offset(5.951292971147453, 23.598931453057713), + const Offset(5.956121008888456, 22.862438898547587), + const Offset(5.976034989369527, 22.3715027919526), + const Offset(5.9932756825730955, 22.093065578347097), + const Offset(5.999985428496359, 22.00019470205062), + const Offset(6.0, 22.0), + ], + const [ + const Offset(39.94921875, 26.0), + const Offset(39.91892748707239, 26.320327277002704), + const Offset(39.76165847505559, 27.44070450686089), + const Offset(39.204067317080856, 29.66482937223119), + const Offset(37.532335710606446, 33.23420478667988), + const Offset(32.93796312691141, 38.04355807552189), + const Offset(26.633976945925774, 40.7074763785527), + const Offset(19.754780569089124, 40.645450453352446), + const Offset(14.258518944641395, 38.42055825640933), + const Offset(10.642329475530556, 35.42591996819203), + const Offset(8.442750176698839, 32.47083890521039), + const Offset(7.175149143375414, 29.871645565973722), + const Offset(6.485980210787691, 27.710284879276827), + const Offset(6.141884684352732, 25.97465660853507), + const Offset(5.994461565155852, 24.620856310443347), + const Offset(5.951292971147453, 23.598931453057713), + const Offset(5.956121008888456, 22.862438898547587), + const Offset(5.976034989369527, 22.3715027919526), + const Offset(5.9932756825730955, 22.093065578347097), + const Offset(5.999985428496359, 22.00019470205062), + const Offset(6.0, 22.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(39.94921875, 26.0), + const Offset(39.91892748707239, 26.320327277002704), + const Offset(39.76165847505559, 27.44070450686089), + const Offset(39.204067317080856, 29.66482937223119), + const Offset(37.532335710606446, 33.23420478667988), + const Offset(32.93796312691141, 38.04355807552189), + const Offset(26.633976945925774, 40.7074763785527), + const Offset(19.754780569089124, 40.645450453352446), + const Offset(14.258518944641395, 38.42055825640933), + const Offset(10.642329475530556, 35.42591996819203), + const Offset(8.442750176698839, 32.47083890521039), + const Offset(7.175149143375414, 29.871645565973722), + const Offset(6.485980210787691, 27.710284879276827), + const Offset(6.141884684352732, 25.97465660853507), + const Offset(5.994461565155852, 24.620856310443347), + const Offset(5.951292971147453, 23.598931453057713), + const Offset(5.956121008888456, 22.862438898547587), + const Offset(5.976034989369527, 22.3715027919526), + const Offset(5.9932756825730955, 22.093065578347097), + const Offset(5.999985428496359, 22.00019470205062), + const Offset(6.0, 22.0), + ], + const [ + const Offset(39.94921875, 22.0), + const Offset(39.999299444085175, 22.321134814951655), + const Offset(40.123697128128484, 23.4571221977224), + const Offset(40.127941008338254, 25.772984385261328), + const Offset(39.36673145070893, 29.679631356759792), + const Offset(36.03000494036236, 35.505984938867314), + const Offset(30.483797891740366, 39.621714579092405), + const Offset(23.719442126984134, 41.17597729654657), + const Offset(17.808469902722187, 40.26388356552361), + const Offset(13.571377486425117, 38.15001206462978), + const Offset(10.73996518894534, 35.74540806580379), + const Offset(8.908677157504997, 33.47648684184537), + const Offset(7.746937054898215, 31.506333856475468), + const Offset(7.021336564573183, 29.876779670456198), + const Offset(6.575233382277915, 28.57846974488041), + const Offset(6.306002369153553, 27.58317306758941), + const Offset(6.147597126684428, 26.85785338221681), + const Offset(6.058558318339831, 26.3706514388743), + const Offset(6.013954859968965, 26.093012124442712), + const Offset(6.000028695609693, 26.000194701816614), + const Offset(6.0, 26.0), + ], + const [ + const Offset(39.94921875, 22.0), + const Offset(39.999299444085175, 22.321134814951655), + const Offset(40.123697128128484, 23.4571221977224), + const Offset(40.127941008338254, 25.772984385261328), + const Offset(39.36673145070893, 29.679631356759792), + const Offset(36.03000494036236, 35.505984938867314), + const Offset(30.483797891740366, 39.621714579092405), + const Offset(23.719442126984134, 41.17597729654657), + const Offset(17.808469902722187, 40.26388356552361), + const Offset(13.571377486425117, 38.15001206462978), + const Offset(10.73996518894534, 35.74540806580379), + const Offset(8.908677157504997, 33.47648684184537), + const Offset(7.746937054898215, 31.506333856475468), + const Offset(7.021336564573183, 29.876779670456198), + const Offset(6.575233382277915, 28.57846974488041), + const Offset(6.306002369153553, 27.58317306758941), + const Offset(6.147597126684428, 26.85785338221681), + const Offset(6.058558318339831, 26.3706514388743), + const Offset(6.013954859968965, 26.093012124442712), + const Offset(6.000028695609693, 26.000194701816614), + const Offset(6.0, 26.0), + ], + ), + const _PathClose( + ), + ], + ), + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(24.00120242935725, 7.98287044589657), + const Offset(24.475307447859166, 8.003617986907148), + const Offset(26.126659093516306, 8.177690670193112), + const Offset(29.352785593371877, 8.997654274881697), + const Offset(34.261760845645924, 11.73586028864448), + const Offset(39.689530947675216, 19.233828052194387), + const Offset(40.483245113546566, 28.57182115613015), + const Offset(36.43819118187483, 37.011448735029944), + const Offset(29.990575804517718, 41.869715613211284), + const Offset(23.79684347484401, 43.53566841500789), + const Offset(18.750267725016194, 43.37984126279926), + const Offset(14.90588210305647, 42.37202895863352), + const Offset(12.06653769423517, 41.068216372655385), + const Offset(10.005013565343445, 39.76135295541911), + const Offset(8.528791010746735, 38.595867902966916), + const Offset(7.490777665658619, 37.63578444828991), + const Offset(6.783719048719078, 36.90231589146764), + const Offset(6.331695603851976, 36.39438332503497), + const Offset(6.082250821137091, 36.09960487240796), + const Offset(6.000171486902083, 36.000208945476956), + const Offset(6.0, 36.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(24.00120242935725, 7.98287044589657), + const Offset(24.475307447859166, 8.003617986907148), + const Offset(26.126659093516306, 8.177690670193112), + const Offset(29.352785593371877, 8.997654274881697), + const Offset(34.261760845645924, 11.73586028864448), + const Offset(39.689530947675216, 19.233828052194387), + const Offset(40.483245113546566, 28.57182115613015), + const Offset(36.43819118187483, 37.011448735029944), + const Offset(29.990575804517718, 41.869715613211284), + const Offset(23.79684347484401, 43.53566841500789), + const Offset(18.750267725016194, 43.37984126279926), + const Offset(14.90588210305647, 42.37202895863352), + const Offset(12.06653769423517, 41.068216372655385), + const Offset(10.005013565343445, 39.76135295541911), + const Offset(8.528791010746735, 38.595867902966916), + const Offset(7.490777665658619, 37.63578444828991), + const Offset(6.783719048719078, 36.90231589146764), + const Offset(6.331695603851976, 36.39438332503497), + const Offset(6.082250821137091, 36.09960487240796), + const Offset(6.000171486902083, 36.000208945476956), + const Offset(6.0, 36.0), + ], + const [ + const Offset(8.389135783884633, 23.59493709136918), + const Offset(8.411539419733579, 23.280020314446016), + const Offset(8.535460203545142, 22.174793784450976), + const Offset(9.004955277979905, 19.95721448439121), + const Offset(10.506583157969082, 16.301391783224325), + const Offset(15.00736732713968, 11.07994257565777), + const Offset(21.799606746441338, 7.957602889938901), + const Offset(29.78681308270101, 8.138822767869717), + const Offset(36.3635225612393, 11.3666818389531), + const Offset(40.53777507406921, 15.843550126760437), + const Offset(42.771588169072636, 20.33326716415372), + const Offset(43.71871364987625, 24.29568645796705), + const Offset(43.90383296365319, 27.574365631376406), + const Offset(43.68696452483883, 30.181901809762802), + const Offset(43.29833346247236, 32.192150096307955), + const Offset(42.87820947711742, 33.69183670134356), + const Offset(42.5074211611244, 34.76136730547495), + const Offset(42.22832709352211, 35.46839060016271), + const Offset(42.058590816793185, 35.86711275140609), + const Offset(42.00012355171139, 35.99972219110006), + const Offset(42.0, 36.0), + ], + const [ + const Offset(8.389135783884633, 23.59493709136918), + const Offset(8.411539419733579, 23.280020314446016), + const Offset(8.535460203545142, 22.174793784450976), + const Offset(9.004955277979905, 19.95721448439121), + const Offset(10.506583157969082, 16.301391783224325), + const Offset(15.00736732713968, 11.07994257565777), + const Offset(21.799606746441338, 7.957602889938901), + const Offset(29.78681308270101, 8.138822767869717), + const Offset(36.3635225612393, 11.3666818389531), + const Offset(40.53777507406921, 15.843550126760437), + const Offset(42.771588169072636, 20.33326716415372), + const Offset(43.71871364987625, 24.29568645796705), + const Offset(43.90383296365319, 27.574365631376406), + const Offset(43.68696452483883, 30.181901809762802), + const Offset(43.29833346247236, 32.192150096307955), + const Offset(42.87820947711742, 33.69183670134356), + const Offset(42.5074211611244, 34.76136730547495), + const Offset(42.22832709352211, 35.46839060016271), + const Offset(42.058590816793185, 35.86711275140609), + const Offset(42.00012355171139, 35.99972219110006), + const Offset(42.0, 36.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(8.389135783884633, 23.59493709136918), + const Offset(8.411539419733579, 23.280020314446016), + const Offset(8.535460203545142, 22.174793784450976), + const Offset(9.004955277979905, 19.95721448439121), + const Offset(10.506583157969082, 16.301391783224325), + const Offset(15.00736732713968, 11.07994257565777), + const Offset(21.799606746441338, 7.957602889938901), + const Offset(29.78681308270101, 8.138822767869717), + const Offset(36.3635225612393, 11.3666818389531), + const Offset(40.53777507406921, 15.843550126760437), + const Offset(42.771588169072636, 20.33326716415372), + const Offset(43.71871364987625, 24.29568645796705), + const Offset(43.90383296365319, 27.574365631376406), + const Offset(43.68696452483883, 30.181901809762802), + const Offset(43.29833346247236, 32.192150096307955), + const Offset(42.87820947711742, 33.69183670134356), + const Offset(42.5074211611244, 34.76136730547495), + const Offset(42.22832709352211, 35.46839060016271), + const Offset(42.058590816793185, 35.86711275140609), + const Offset(42.00012355171139, 35.99972219110006), + const Offset(42.0, 36.0), + ], + const [ + const Offset(11.217562908630821, 26.423364216115367), + const Offset(11.168037593988725, 26.178591999833156), + const Offset(11.026001684399013, 25.304842207741935), + const Offset(10.901761927954412, 23.478879507162752), + const Offset(11.261530717110908, 20.229502548330856), + const Offset(13.752640365544114, 14.878055298029915), + const Offset(18.8358022450215, 10.643838709326973), + const Offset(25.888907364460923, 9.03678212759111), + const Offset(32.44806665065668, 10.54863232194106), + const Offset(37.11467529624949, 13.774157000481484), + const Offset(40.00232975553069, 17.44688398809633), + const Offset(41.592943181014675, 20.907309278000795), + const Offset(42.34289639575017, 23.891503017731534), + const Offset(42.59272365615382, 26.334482295166104), + const Offset(42.57381482854062, 28.258313197161566), + const Offset(42.4351505629611, 29.71645007881405), + const Offset(42.26812747456164, 30.76853140456803), + const Offset(42.125177049114, 31.469720812803587), + const Offset(42.03274190981708, 31.867196273027055), + const Offset(42.00006946781973, 31.999722191465697), + const Offset(42.0, 32.0), + ], + const [ + const Offset(11.217562908630821, 26.423364216115367), + const Offset(11.168037593988725, 26.178591999833156), + const Offset(11.026001684399013, 25.304842207741935), + const Offset(10.901761927954412, 23.478879507162752), + const Offset(11.261530717110908, 20.229502548330856), + const Offset(13.752640365544114, 14.878055298029915), + const Offset(18.8358022450215, 10.643838709326973), + const Offset(25.888907364460923, 9.03678212759111), + const Offset(32.44806665065668, 10.54863232194106), + const Offset(37.11467529624949, 13.774157000481484), + const Offset(40.00232975553069, 17.44688398809633), + const Offset(41.592943181014675, 20.907309278000795), + const Offset(42.34289639575017, 23.891503017731534), + const Offset(42.59272365615382, 26.334482295166104), + const Offset(42.57381482854062, 28.258313197161566), + const Offset(42.4351505629611, 29.71645007881405), + const Offset(42.26812747456164, 30.76853140456803), + const Offset(42.125177049114, 31.469720812803587), + const Offset(42.03274190981708, 31.867196273027055), + const Offset(42.00006946781973, 31.999722191465697), + const Offset(42.0, 32.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(11.217562908630821, 26.423364216115367), + const Offset(11.168037593988725, 26.178591999833156), + const Offset(11.026001684399013, 25.304842207741935), + const Offset(10.901761927954412, 23.478879507162752), + const Offset(11.261530717110908, 20.229502548330856), + const Offset(13.752640365544114, 14.878055298029915), + const Offset(18.8358022450215, 10.643838709326973), + const Offset(25.888907364460923, 9.03678212759111), + const Offset(32.44806665065668, 10.54863232194106), + const Offset(37.11467529624949, 13.774157000481484), + const Offset(40.00232975553069, 17.44688398809633), + const Offset(41.592943181014675, 20.907309278000795), + const Offset(42.34289639575017, 23.891503017731534), + const Offset(42.59272365615382, 26.334482295166104), + const Offset(42.57381482854062, 28.258313197161566), + const Offset(42.4351505629611, 29.71645007881405), + const Offset(42.26812747456164, 30.76853140456803), + const Offset(42.125177049114, 31.469720812803587), + const Offset(42.03274190981708, 31.867196273027055), + const Offset(42.00006946781973, 31.999722191465697), + const Offset(42.0, 32.0), + ], + const [ + const Offset(26.829629554103438, 10.811297570642758), + const Offset(27.231805622114308, 10.902189672294288), + const Offset(28.61720057437018, 11.307739093484066), + const Offset(31.249592243346385, 12.519319297653237), + const Offset(35.01670840478775, 15.663971053751007), + const Offset(38.43480398607965, 23.031940774566532), + const Offset(37.51944061212673, 31.258056975518222), + const Offset(32.54028546363474, 37.909408094751335), + const Offset(26.0751198939351, 41.05166609619924), + const Offset(20.373743697024292, 41.46627528872894), + const Offset(15.981009311474246, 40.49345808674188), + const Offset(12.780111634194903, 38.983651778667266), + const Offset(10.505601126332149, 37.38535375901051), + const Offset(8.910772696658444, 35.91393344082242), + const Offset(7.804272376814996, 34.66203100382052), + const Offset(7.047718751502295, 33.6603978257604), + const Offset(6.544425362156314, 32.90947999056071), + const Offset(6.228545559443866, 32.39571353767585), + const Offset(6.056401914160979, 32.099688394028924), + const Offset(6.000117403010417, 32.00020894584259), + const Offset(6.0, 32.0), + ], + const [ + const Offset(26.829629554103438, 10.811297570642758), + const Offset(27.231805622114308, 10.902189672294288), + const Offset(28.61720057437018, 11.307739093484066), + const Offset(31.249592243346385, 12.519319297653237), + const Offset(35.01670840478775, 15.663971053751007), + const Offset(38.43480398607965, 23.031940774566532), + const Offset(37.51944061212673, 31.258056975518222), + const Offset(32.54028546363474, 37.909408094751335), + const Offset(26.0751198939351, 41.05166609619924), + const Offset(20.373743697024292, 41.46627528872894), + const Offset(15.981009311474246, 40.49345808674188), + const Offset(12.780111634194903, 38.983651778667266), + const Offset(10.505601126332149, 37.38535375901051), + const Offset(8.910772696658444, 35.91393344082242), + const Offset(7.804272376814996, 34.66203100382052), + const Offset(7.047718751502295, 33.6603978257604), + const Offset(6.544425362156314, 32.90947999056071), + const Offset(6.228545559443866, 32.39571353767585), + const Offset(6.056401914160979, 32.099688394028924), + const Offset(6.000117403010417, 32.00020894584259), + const Offset(6.0, 32.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(26.829629554103438, 10.811297570642758), + const Offset(27.231805622114308, 10.902189672294288), + const Offset(28.61720057437018, 11.307739093484066), + const Offset(31.249592243346385, 12.519319297653237), + const Offset(35.01670840478775, 15.663971053751007), + const Offset(38.43480398607965, 23.031940774566532), + const Offset(37.51944061212673, 31.258056975518222), + const Offset(32.54028546363474, 37.909408094751335), + const Offset(26.0751198939351, 41.05166609619924), + const Offset(20.373743697024292, 41.46627528872894), + const Offset(15.981009311474246, 40.49345808674188), + const Offset(12.780111634194903, 38.983651778667266), + const Offset(10.505601126332149, 37.38535375901051), + const Offset(8.910772696658444, 35.91393344082242), + const Offset(7.804272376814996, 34.66203100382052), + const Offset(7.047718751502295, 33.6603978257604), + const Offset(6.544425362156314, 32.90947999056071), + const Offset(6.228545559443866, 32.39571353767585), + const Offset(6.056401914160979, 32.099688394028924), + const Offset(6.000117403010417, 32.00020894584259), + const Offset(6.0, 32.0), + ], + const [ + const Offset(24.00120242935725, 7.98287044589657), + const Offset(24.475307447859166, 8.003617986907148), + const Offset(26.126659093516306, 8.177690670193112), + const Offset(29.352785593371877, 8.997654274881697), + const Offset(34.261760845645924, 11.73586028864448), + const Offset(39.689530947675216, 19.233828052194387), + const Offset(40.483245113546566, 28.57182115613015), + const Offset(36.43819118187483, 37.011448735029944), + const Offset(29.990575804517718, 41.869715613211284), + const Offset(23.79684347484401, 43.53566841500789), + const Offset(18.750267725016194, 43.37984126279926), + const Offset(14.90588210305647, 42.37202895863352), + const Offset(12.06653769423517, 41.068216372655385), + const Offset(10.005013565343445, 39.76135295541911), + const Offset(8.528791010746735, 38.595867902966916), + const Offset(7.490777665658619, 37.63578444828991), + const Offset(6.783719048719078, 36.90231589146764), + const Offset(6.331695603851976, 36.39438332503497), + const Offset(6.082250821137091, 36.09960487240796), + const Offset(6.000171486902083, 36.000208945476956), + const Offset(6.0, 36.0), + ], + const [ + const Offset(24.00120242935725, 7.98287044589657), + const Offset(24.475307447859166, 8.003617986907148), + const Offset(26.126659093516306, 8.177690670193112), + const Offset(29.352785593371877, 8.997654274881697), + const Offset(34.261760845645924, 11.73586028864448), + const Offset(39.689530947675216, 19.233828052194387), + const Offset(40.483245113546566, 28.57182115613015), + const Offset(36.43819118187483, 37.011448735029944), + const Offset(29.990575804517718, 41.869715613211284), + const Offset(23.79684347484401, 43.53566841500789), + const Offset(18.750267725016194, 43.37984126279926), + const Offset(14.90588210305647, 42.37202895863352), + const Offset(12.06653769423517, 41.068216372655385), + const Offset(10.005013565343445, 39.76135295541911), + const Offset(8.528791010746735, 38.595867902966916), + const Offset(7.490777665658619, 37.63578444828991), + const Offset(6.783719048719078, 36.90231589146764), + const Offset(6.331695603851976, 36.39438332503497), + const Offset(6.082250821137091, 36.09960487240796), + const Offset(6.000171486902083, 36.000208945476956), + const Offset(6.0, 36.0), + ], + ), + const _PathClose( + ), + ], + ), + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(26.829629554103434, 37.188702429357235), + const Offset(26.70295401712204, 37.21708146835027), + const Offset(26.253437940457104, 37.31668297706097), + const Offset(25.316159296509255, 37.51407939114749), + const Offset(23.588416071597663, 37.80897683895165), + const Offset(20.234451203252327, 37.9685842890323), + const Offset(16.265106286835728, 37.25239920809595), + const Offset(12.10312127594884, 35.1746313573166), + const Offset(8.858593681675742, 32.111920483700914), + const Offset(6.842177615689938, 28.881561047964333), + const Offset(5.761956468124708, 25.926691322240227), + const Offset(5.290469810431201, 23.40907221160189), + const Offset(5.178751382636996, 21.349132840198116), + const Offset(5.258916359304976, 19.710667345993283), + const Offset(5.423821188616003, 18.440676377623248), + const Offset(5.607765949538116, 17.48625665894383), + const Offset(5.772423819137188, 16.80059820468561), + const Offset(5.897326348355019, 16.34455713877282), + const Offset(5.973614735709873, 16.086271507697752), + const Offset(5.9999443342489265, 16.000180457509614), + const Offset(6.0, 16.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(26.829629554103434, 37.188702429357235), + const Offset(26.70295401712204, 37.21708146835027), + const Offset(26.253437940457104, 37.31668297706097), + const Offset(25.316159296509255, 37.51407939114749), + const Offset(23.588416071597663, 37.80897683895165), + const Offset(20.234451203252327, 37.9685842890323), + const Offset(16.265106286835728, 37.25239920809595), + const Offset(12.10312127594884, 35.1746313573166), + const Offset(8.858593681675742, 32.111920483700914), + const Offset(6.842177615689938, 28.881561047964333), + const Offset(5.761956468124708, 25.926691322240227), + const Offset(5.290469810431201, 23.40907221160189), + const Offset(5.178751382636996, 21.349132840198116), + const Offset(5.258916359304976, 19.710667345993283), + const Offset(5.423821188616003, 18.440676377623248), + const Offset(5.607765949538116, 17.48625665894383), + const Offset(5.772423819137188, 16.80059820468561), + const Offset(5.897326348355019, 16.34455713877282), + const Offset(5.973614735709873, 16.086271507697752), + const Offset(5.9999443342489265, 16.000180457509614), + const Offset(6.0, 16.0), + ], + const [ + const Offset(11.2175487664952, 21.576649926020245), + const Offset(11.26591566746795, 21.307620185014063), + const Offset(11.473792301821605, 20.377637880770784), + const Offset(12.06502589368821, 18.578567196580664), + const Offset(13.54646415229777, 15.801892832848761), + const Offset(17.052481673761243, 12.16993860231353), + const Offset(21.42462731807053, 9.9137145270952), + const Offset(26.111676903911107, 9.066591789474842), + const Offset(30.142827978195022, 9.351628521416771), + const Offset(33.249292834290536, 10.17924910714327), + const Offset(35.60828563949723, 11.183386110908502), + const Offset(37.40014550074941, 12.188459616498097), + const Offset(38.76213503811523, 13.111795882844753), + const Offset(39.793775377370764, 13.915564474413902), + const Offset(40.567255045797005, 14.584805428587808), + const Offset(41.13536943122808, 15.116774671440997), + const Offset(41.537143495419784, 15.5155379179047), + const Offset(41.801600251554405, 15.788922082526666), + const Offset(41.95043550915973, 15.946775613712157), + const Offset(41.99989640116428, 15.999888404883473), + const Offset(42.0, 16.0), + ], + const [ + const Offset(11.2175487664952, 21.576649926020245), + const Offset(11.26591566746795, 21.307620185014063), + const Offset(11.473792301821605, 20.377637880770784), + const Offset(12.06502589368821, 18.578567196580664), + const Offset(13.54646415229777, 15.801892832848761), + const Offset(17.052481673761243, 12.16993860231353), + const Offset(21.42462731807053, 9.9137145270952), + const Offset(26.111676903911107, 9.066591789474842), + const Offset(30.142827978195022, 9.351628521416771), + const Offset(33.249292834290536, 10.17924910714327), + const Offset(35.60828563949723, 11.183386110908502), + const Offset(37.40014550074941, 12.188459616498097), + const Offset(38.76213503811523, 13.111795882844753), + const Offset(39.793775377370764, 13.915564474413902), + const Offset(40.567255045797005, 14.584805428587808), + const Offset(41.13536943122808, 15.116774671440997), + const Offset(41.537143495419784, 15.5155379179047), + const Offset(41.801600251554405, 15.788922082526666), + const Offset(41.95043550915973, 15.946775613712157), + const Offset(41.99989640116428, 15.999888404883473), + const Offset(42.0, 16.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(11.2175487664952, 21.576649926020245), + const Offset(11.26591566746795, 21.307620185014063), + const Offset(11.473792301821605, 20.377637880770784), + const Offset(12.06502589368821, 18.578567196580664), + const Offset(13.54646415229777, 15.801892832848761), + const Offset(17.052481673761243, 12.16993860231353), + const Offset(21.42462731807053, 9.9137145270952), + const Offset(26.111676903911107, 9.066591789474842), + const Offset(30.142827978195022, 9.351628521416771), + const Offset(33.249292834290536, 10.17924910714327), + const Offset(35.60828563949723, 11.183386110908502), + const Offset(37.40014550074941, 12.188459616498097), + const Offset(38.76213503811523, 13.111795882844753), + const Offset(39.793775377370764, 13.915564474413902), + const Offset(40.567255045797005, 14.584805428587808), + const Offset(41.13536943122808, 15.116774671440997), + const Offset(41.537143495419784, 15.5155379179047), + const Offset(41.801600251554405, 15.788922082526666), + const Offset(41.95043550915973, 15.946775613712157), + const Offset(41.99989640116428, 15.999888404883473), + const Offset(42.0, 16.0), + ], + const [ + const Offset(8.38912164174901, 24.405077050766437), + const Offset(8.395184821848037, 24.09310118692493), + const Offset(8.459782153583708, 23.007417876572518), + const Offset(8.787794358833729, 20.871982437428983), + const Offset(9.907414129760891, 17.4624092987335), + const Offset(13.082563535366404, 12.659581303110395), + const Offset(17.494014200747685, 9.171905574648836), + const Offset(22.5870000408063, 7.175387672861925), + const Offset(27.221252362148654, 6.6195238529014375), + const Offset(30.937448027657968, 6.914992133489694), + const Offset(33.83674155554175, 7.597074418012536), + const Offset(36.08060605872299, 8.412374916582504), + const Offset(37.809259485732085, 9.226949916571378), + const Offset(39.13181277597566, 9.970719038360135), + const Offset(40.13100060158848, 10.608666338979862), + const Offset(40.8691843334897, 11.125641311887346), + const Offset(41.393512389333864, 11.518117486505904), + const Offset(41.739705833610245, 11.789400976065625), + const Offset(41.934926095887384, 11.946805681562672), + const Offset(41.99986395082928, 11.999888405015101), + const Offset(42.0, 12.0), + ], + const [ + const Offset(8.38912164174901, 24.405077050766437), + const Offset(8.395184821848037, 24.09310118692493), + const Offset(8.459782153583708, 23.007417876572518), + const Offset(8.787794358833729, 20.871982437428983), + const Offset(9.907414129760891, 17.4624092987335), + const Offset(13.082563535366404, 12.659581303110395), + const Offset(17.494014200747685, 9.171905574648836), + const Offset(22.5870000408063, 7.175387672861925), + const Offset(27.221252362148654, 6.6195238529014375), + const Offset(30.937448027657968, 6.914992133489694), + const Offset(33.83674155554175, 7.597074418012536), + const Offset(36.08060605872299, 8.412374916582504), + const Offset(37.809259485732085, 9.226949916571378), + const Offset(39.13181277597566, 9.970719038360135), + const Offset(40.13100060158848, 10.608666338979862), + const Offset(40.8691843334897, 11.125641311887346), + const Offset(41.393512389333864, 11.518117486505904), + const Offset(41.739705833610245, 11.789400976065625), + const Offset(41.934926095887384, 11.946805681562672), + const Offset(41.99986395082928, 11.999888405015101), + const Offset(42.0, 12.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(8.38912164174901, 24.405077050766437), + const Offset(8.395184821848037, 24.09310118692493), + const Offset(8.459782153583708, 23.007417876572518), + const Offset(8.787794358833729, 20.871982437428983), + const Offset(9.907414129760891, 17.4624092987335), + const Offset(13.082563535366404, 12.659581303110395), + const Offset(17.494014200747685, 9.171905574648836), + const Offset(22.5870000408063, 7.175387672861925), + const Offset(27.221252362148654, 6.6195238529014375), + const Offset(30.937448027657968, 6.914992133489694), + const Offset(33.83674155554175, 7.597074418012536), + const Offset(36.08060605872299, 8.412374916582504), + const Offset(37.809259485732085, 9.226949916571378), + const Offset(39.13181277597566, 9.970719038360135), + const Offset(40.13100060158848, 10.608666338979862), + const Offset(40.8691843334897, 11.125641311887346), + const Offset(41.393512389333864, 11.518117486505904), + const Offset(41.739705833610245, 11.789400976065625), + const Offset(41.934926095887384, 11.946805681562672), + const Offset(41.99986395082928, 11.999888405015101), + const Offset(42.0, 12.0), + ], + const [ + const Offset(24.001202429357242, 40.01712955410343), + const Offset(23.83222317150212, 40.00256247026114), + const Offset(23.23942779221921, 39.946462972862705), + const Offset(22.038927761654776, 39.80749463199581), + const Offset(19.949366049060785, 39.46949330483639), + const Offset(16.264533064857485, 38.458226989829164), + const Offset(12.33449316951288, 36.51059025564959), + const Offset(8.578444412844032, 33.28342724070369), + const Offset(5.937018065629374, 29.37981581518558), + const Offset(4.53033280905737, 25.617304074310752), + const Offset(3.9904123841692254, 22.340379629344262), + const Offset(3.9709303684047867, 19.632987511686302), + const Offset(4.225875830253855, 17.46428687392474), + const Offset(4.596953757909873, 15.765821909939516), + const Offset(4.987566744407481, 14.464537288015299), + const Offset(5.341580851799733, 13.495123299390182), + const Offset(5.628792713051272, 12.803177773286812), + const Offset(5.835431930410859, 12.34503603231178), + const Offset(5.958105322437522, 12.08630157554827), + const Offset(5.999911883913924, 12.000180457641243), + const Offset(6.0, 12.0), + ], + const [ + const Offset(24.001202429357242, 40.01712955410343), + const Offset(23.83222317150212, 40.00256247026114), + const Offset(23.23942779221921, 39.946462972862705), + const Offset(22.038927761654776, 39.80749463199581), + const Offset(19.949366049060785, 39.46949330483639), + const Offset(16.264533064857485, 38.458226989829164), + const Offset(12.33449316951288, 36.51059025564959), + const Offset(8.578444412844032, 33.28342724070369), + const Offset(5.937018065629374, 29.37981581518558), + const Offset(4.53033280905737, 25.617304074310752), + const Offset(3.9904123841692254, 22.340379629344262), + const Offset(3.9709303684047867, 19.632987511686302), + const Offset(4.225875830253855, 17.46428687392474), + const Offset(4.596953757909873, 15.765821909939516), + const Offset(4.987566744407481, 14.464537288015299), + const Offset(5.341580851799733, 13.495123299390182), + const Offset(5.628792713051272, 12.803177773286812), + const Offset(5.835431930410859, 12.34503603231178), + const Offset(5.958105322437522, 12.08630157554827), + const Offset(5.999911883913924, 12.000180457641243), + const Offset(6.0, 12.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(24.001202429357242, 40.01712955410343), + const Offset(23.83222317150212, 40.00256247026114), + const Offset(23.23942779221921, 39.946462972862705), + const Offset(22.038927761654776, 39.80749463199581), + const Offset(19.949366049060785, 39.46949330483639), + const Offset(16.264533064857485, 38.458226989829164), + const Offset(12.33449316951288, 36.51059025564959), + const Offset(8.578444412844032, 33.28342724070369), + const Offset(5.937018065629374, 29.37981581518558), + const Offset(4.53033280905737, 25.617304074310752), + const Offset(3.9904123841692254, 22.340379629344262), + const Offset(3.9709303684047867, 19.632987511686302), + const Offset(4.225875830253855, 17.46428687392474), + const Offset(4.596953757909873, 15.765821909939516), + const Offset(4.987566744407481, 14.464537288015299), + const Offset(5.341580851799733, 13.495123299390182), + const Offset(5.628792713051272, 12.803177773286812), + const Offset(5.835431930410859, 12.34503603231178), + const Offset(5.958105322437522, 12.08630157554827), + const Offset(5.999911883913924, 12.000180457641243), + const Offset(6.0, 12.0), + ], + const [ + const Offset(26.829629554103434, 37.188702429357235), + const Offset(26.70295401712204, 37.21708146835027), + const Offset(26.253437940457104, 37.31668297706097), + const Offset(25.316159296509255, 37.51407939114749), + const Offset(23.588416071597663, 37.80897683895165), + const Offset(20.234451203252327, 37.9685842890323), + const Offset(16.265106286835728, 37.25239920809595), + const Offset(12.10312127594884, 35.1746313573166), + const Offset(8.858593681675742, 32.111920483700914), + const Offset(6.842177615689938, 28.881561047964333), + const Offset(5.761956468124708, 25.926691322240227), + const Offset(5.290469810431201, 23.40907221160189), + const Offset(5.178751382636996, 21.349132840198116), + const Offset(5.258916359304976, 19.710667345993283), + const Offset(5.423821188616003, 18.440676377623248), + const Offset(5.607765949538116, 17.48625665894383), + const Offset(5.772423819137188, 16.80059820468561), + const Offset(5.897326348355019, 16.34455713877282), + const Offset(5.973614735709873, 16.086271507697752), + const Offset(5.9999443342489265, 16.000180457509614), + const Offset(6.0, 16.0), + ], + const [ + const Offset(26.829629554103434, 37.188702429357235), + const Offset(26.70295401712204, 37.21708146835027), + const Offset(26.253437940457104, 37.31668297706097), + const Offset(25.316159296509255, 37.51407939114749), + const Offset(23.588416071597663, 37.80897683895165), + const Offset(20.234451203252327, 37.9685842890323), + const Offset(16.265106286835728, 37.25239920809595), + const Offset(12.10312127594884, 35.1746313573166), + const Offset(8.858593681675742, 32.111920483700914), + const Offset(6.842177615689938, 28.881561047964333), + const Offset(5.761956468124708, 25.926691322240227), + const Offset(5.290469810431201, 23.40907221160189), + const Offset(5.178751382636996, 21.349132840198116), + const Offset(5.258916359304976, 19.710667345993283), + const Offset(5.423821188616003, 18.440676377623248), + const Offset(5.607765949538116, 17.48625665894383), + const Offset(5.772423819137188, 16.80059820468561), + const Offset(5.897326348355019, 16.34455713877282), + const Offset(5.973614735709873, 16.086271507697752), + const Offset(5.9999443342489265, 16.000180457509614), + const Offset(6.0, 16.0), + ], + ), + const _PathClose( + ), + ], + ), + ], + matchTextDirection: true, +); diff --git a/packages/flutter/lib/src/material_animated_icons/data/menu_arrow.g.dart b/packages/flutter/lib/src/material_animated_icons/data/menu_arrow.g.dart new file mode 100644 index 0000000000..484b104a4d --- /dev/null +++ b/packages/flutter/lib/src/material_animated_icons/data/menu_arrow.g.dart @@ -0,0 +1,1027 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// AUTOGENERATED FILE DO NOT EDIT! +// This file was generated by vitool. +part of material_animated_icons; +const _AnimatedIconData _$menu_arrow = const _AnimatedIconData( + const Size(48.0, 48.0), + const <_PathFrames>[ + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(6.0, 26.0), + const Offset(5.976562557689849, 25.638185989482512), + const Offset(5.951781669661045, 24.367972149512962), + const Offset(6.172793116155802, 21.823631861702058), + const Offset(7.363587976838016, 17.665129222832853), + const Offset(11.400806749308899, 11.800457098273661), + const Offset(17.41878573585796, 8.03287301910486), + const Offset(24.257523532175192, 6.996159828679087), + const Offset(29.90338248135665, 8.291042849526), + const Offset(33.76252909490214, 10.56619705548221), + const Offset(36.23501636298456, 12.973675163618006), + const Offset(37.77053540180521, 15.158665125787222), + const Offset(38.70420448893307, 17.008159945496722), + const Offset(39.260392038988186, 18.5104805430827), + const Offset(39.58393261852967, 19.691668944482075), + const Offset(39.766765502294305, 20.58840471665747), + const Offset(39.866421084642994, 21.237322746452932), + const Offset(39.91802804639694, 21.671102155152063), + const Offset(39.94204075298555, 21.917555098992118), + const Offset(39.94920417650143, 21.999827480806236), + const Offset(39.94921875, 22.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 26.0), + const Offset(5.976562557689849, 25.638185989482512), + const Offset(5.951781669661045, 24.367972149512962), + const Offset(6.172793116155802, 21.823631861702058), + const Offset(7.363587976838016, 17.665129222832853), + const Offset(11.400806749308899, 11.800457098273661), + const Offset(17.41878573585796, 8.03287301910486), + const Offset(24.257523532175192, 6.996159828679087), + const Offset(29.90338248135665, 8.291042849526), + const Offset(33.76252909490214, 10.56619705548221), + const Offset(36.23501636298456, 12.973675163618006), + const Offset(37.77053540180521, 15.158665125787222), + const Offset(38.70420448893307, 17.008159945496722), + const Offset(39.260392038988186, 18.5104805430827), + const Offset(39.58393261852967, 19.691668944482075), + const Offset(39.766765502294305, 20.58840471665747), + const Offset(39.866421084642994, 21.237322746452932), + const Offset(39.91802804639694, 21.671102155152063), + const Offset(39.94204075298555, 21.917555098992118), + const Offset(39.94920417650143, 21.999827480806236), + const Offset(39.94921875, 22.0), + ], + const [ + const Offset(42.0, 26.0), + const Offset(41.91421333157091, 26.360426629492423), + const Offset(41.55655262500356, 27.60382930516768), + const Offset(40.57766190556539, 29.99090297157744), + const Offset(38.19401046368096, 33.57567286235671), + const Offset(32.70215654116029, 37.756226919427284), + const Offset(26.22621984436523, 39.26167875408963), + const Offset(20.102351173097617, 38.04803275423973), + const Offset(15.903199608216863, 35.25316524725598), + const Offset(13.57741782841064, 32.27000071222682), + const Offset(12.442030802775209, 29.665215617986277), + const Offset(11.981806515947115, 27.560177578292762), + const Offset(11.879421136842055, 25.918712565594948), + const Offset(11.95091483982305, 24.66543021784112), + const Offset(12.092167805674123, 23.72603017548901), + const Offset(12.245452640806768, 23.03857447590349), + const Offset(12.379956070248545, 22.554583229506296), + const Offset(12.480582865035407, 22.237279988168645), + const Offset(12.541514124262473, 22.059212079933666), + const Offset(12.562455771803593, 22.000123717314214), + const Offset(12.562499999999996, 22.000000000000004), + ], + const [ + const Offset(42.0, 26.0), + const Offset(41.91421333157091, 26.360426629492423), + const Offset(41.55655262500356, 27.60382930516768), + const Offset(40.57766190556539, 29.99090297157744), + const Offset(38.19401046368096, 33.57567286235671), + const Offset(32.70215654116029, 37.756226919427284), + const Offset(26.22621984436523, 39.26167875408963), + const Offset(20.102351173097617, 38.04803275423973), + const Offset(15.903199608216863, 35.25316524725598), + const Offset(13.57741782841064, 32.27000071222682), + const Offset(12.442030802775209, 29.665215617986277), + const Offset(11.981806515947115, 27.560177578292762), + const Offset(11.879421136842055, 25.918712565594948), + const Offset(11.95091483982305, 24.66543021784112), + const Offset(12.092167805674123, 23.72603017548901), + const Offset(12.245452640806768, 23.03857447590349), + const Offset(12.379956070248545, 22.554583229506296), + const Offset(12.480582865035407, 22.237279988168645), + const Offset(12.541514124262473, 22.059212079933666), + const Offset(12.562455771803593, 22.000123717314214), + const Offset(12.562499999999996, 22.000000000000004), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 26.0), + const Offset(41.91421333157091, 26.360426629492423), + const Offset(41.55655262500356, 27.60382930516768), + const Offset(40.57766190556539, 29.99090297157744), + const Offset(38.19401046368096, 33.57567286235671), + const Offset(32.70215654116029, 37.756226919427284), + const Offset(26.22621984436523, 39.26167875408963), + const Offset(20.102351173097617, 38.04803275423973), + const Offset(15.903199608216863, 35.25316524725598), + const Offset(13.57741782841064, 32.27000071222682), + const Offset(12.442030802775209, 29.665215617986277), + const Offset(11.981806515947115, 27.560177578292762), + const Offset(11.879421136842055, 25.918712565594948), + const Offset(11.95091483982305, 24.66543021784112), + const Offset(12.092167805674123, 23.72603017548901), + const Offset(12.245452640806768, 23.03857447590349), + const Offset(12.379956070248545, 22.554583229506296), + const Offset(12.480582865035407, 22.237279988168645), + const Offset(12.541514124262473, 22.059212079933666), + const Offset(12.562455771803593, 22.000123717314214), + const Offset(12.562499999999996, 22.000000000000004), + ], + const [ + const Offset(42.0, 22.0), + const Offset(41.99458528858859, 22.361234167441474), + const Offset(41.91859127809106, 23.620246996030513), + const Offset(41.501535596836376, 26.09905798461081), + const Offset(40.02840620381446, 30.021099432452637), + const Offset(35.79419835461124, 35.2186537827727), + const Offset(30.076040790179817, 38.175916954629336), + const Offset(24.067012730992623, 38.57855959743385), + const Offset(19.453150566288006, 37.096490556388844), + const Offset(16.506465839286186, 34.99409280868502), + const Offset(14.73924581501028, 32.939784778587686), + const Offset(13.715334530064114, 31.165018854170466), + const Offset(13.140377980959201, 29.714761542791386), + const Offset(12.83036672005031, 28.56755327976071), + const Offset(12.672939622830032, 27.683643609921106), + const Offset(12.600162038813565, 27.02281609043513), + const Offset(12.571432188039635, 26.54999771317575), + const Offset(12.56310619400641, 26.23642863509033), + const Offset(12.562193301685781, 26.059158626029138), + const Offset(12.562499038934627, 26.000123717080207), + const Offset(12.562499999999996, 26.000000000000004), + ], + const [ + const Offset(42.0, 22.0), + const Offset(41.99458528858859, 22.361234167441474), + const Offset(41.91859127809106, 23.620246996030513), + const Offset(41.501535596836376, 26.09905798461081), + const Offset(40.02840620381446, 30.021099432452637), + const Offset(35.79419835461124, 35.2186537827727), + const Offset(30.076040790179817, 38.175916954629336), + const Offset(24.067012730992623, 38.57855959743385), + const Offset(19.453150566288006, 37.096490556388844), + const Offset(16.506465839286186, 34.99409280868502), + const Offset(14.73924581501028, 32.939784778587686), + const Offset(13.715334530064114, 31.165018854170466), + const Offset(13.140377980959201, 29.714761542791386), + const Offset(12.83036672005031, 28.56755327976071), + const Offset(12.672939622830032, 27.683643609921106), + const Offset(12.600162038813565, 27.02281609043513), + const Offset(12.571432188039635, 26.54999771317575), + const Offset(12.56310619400641, 26.23642863509033), + const Offset(12.562193301685781, 26.059158626029138), + const Offset(12.562499038934627, 26.000123717080207), + const Offset(12.562499999999996, 26.000000000000004), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 22.0), + const Offset(41.99458528858859, 22.361234167441474), + const Offset(41.91859127809106, 23.620246996030513), + const Offset(41.501535596836376, 26.09905798461081), + const Offset(40.02840620381446, 30.021099432452637), + const Offset(35.79419835461124, 35.2186537827727), + const Offset(30.076040790179817, 38.175916954629336), + const Offset(24.067012730992623, 38.57855959743385), + const Offset(19.453150566288006, 37.096490556388844), + const Offset(16.506465839286186, 34.99409280868502), + const Offset(14.73924581501028, 32.939784778587686), + const Offset(13.715334530064114, 31.165018854170466), + const Offset(13.140377980959201, 29.714761542791386), + const Offset(12.83036672005031, 28.56755327976071), + const Offset(12.672939622830032, 27.683643609921106), + const Offset(12.600162038813565, 27.02281609043513), + const Offset(12.571432188039635, 26.54999771317575), + const Offset(12.56310619400641, 26.23642863509033), + const Offset(12.562193301685781, 26.059158626029138), + const Offset(12.562499038934627, 26.000123717080207), + const Offset(12.562499999999996, 26.000000000000004), + ], + const [ + const Offset(6.0, 22.0), + const Offset(6.056934514707525, 21.63899352743156), + const Offset(6.3138203227485405, 20.384389840375796), + const Offset(7.096666807426793, 17.931786874735423), + const Offset(9.197983716971518, 14.110555792928775), + const Offset(14.492848562759846, 9.262883961619078), + const Offset(21.26860668167255, 6.947111219644562), + const Offset(28.222185090070198, 7.526686671873211), + const Offset(33.453333439427794, 10.134368158658866), + const Offset(36.69157710577769, 13.290289151940406), + const Offset(38.53223137521963, 16.248244324219414), + const Offset(39.50406341592221, 18.763506401664923), + const Offset(39.965161333050226, 20.80420892269316), + const Offset(40.139843919215444, 22.41260360500229), + const Offset(40.164704435685586, 23.649282378914172), + const Offset(40.1214749003011, 24.572646331189105), + const Offset(40.057897202434084, 25.232737230122385), + const Offset(40.00055137536795, 25.670250802073745), + const Offset(39.96271993040885, 25.917501645087587), + const Offset(39.949247443632466, 25.99982748057223), + const Offset(39.94921875, 26.0), + ], + const [ + const Offset(6.0, 22.0), + const Offset(6.056934514707525, 21.63899352743156), + const Offset(6.3138203227485405, 20.384389840375796), + const Offset(7.096666807426793, 17.931786874735423), + const Offset(9.197983716971518, 14.110555792928775), + const Offset(14.492848562759846, 9.262883961619078), + const Offset(21.26860668167255, 6.947111219644562), + const Offset(28.222185090070198, 7.526686671873211), + const Offset(33.453333439427794, 10.134368158658866), + const Offset(36.69157710577769, 13.290289151940406), + const Offset(38.53223137521963, 16.248244324219414), + const Offset(39.50406341592221, 18.763506401664923), + const Offset(39.965161333050226, 20.80420892269316), + const Offset(40.139843919215444, 22.41260360500229), + const Offset(40.164704435685586, 23.649282378914172), + const Offset(40.1214749003011, 24.572646331189105), + const Offset(40.057897202434084, 25.232737230122385), + const Offset(40.00055137536795, 25.670250802073745), + const Offset(39.96271993040885, 25.917501645087587), + const Offset(39.949247443632466, 25.99982748057223), + const Offset(39.94921875, 26.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 22.0), + const Offset(6.056934514707525, 21.63899352743156), + const Offset(6.3138203227485405, 20.384389840375796), + const Offset(7.096666807426793, 17.931786874735423), + const Offset(9.197983716971518, 14.110555792928775), + const Offset(14.492848562759846, 9.262883961619078), + const Offset(21.26860668167255, 6.947111219644562), + const Offset(28.222185090070198, 7.526686671873211), + const Offset(33.453333439427794, 10.134368158658866), + const Offset(36.69157710577769, 13.290289151940406), + const Offset(38.53223137521963, 16.248244324219414), + const Offset(39.50406341592221, 18.763506401664923), + const Offset(39.965161333050226, 20.80420892269316), + const Offset(40.139843919215444, 22.41260360500229), + const Offset(40.164704435685586, 23.649282378914172), + const Offset(40.1214749003011, 24.572646331189105), + const Offset(40.057897202434084, 25.232737230122385), + const Offset(40.00055137536795, 25.670250802073745), + const Offset(39.96271993040885, 25.917501645087587), + const Offset(39.949247443632466, 25.99982748057223), + const Offset(39.94921875, 26.0), + ], + const [ + const Offset(6.0, 26.0), + const Offset(5.976562557689849, 25.638185989482512), + const Offset(5.951781669661045, 24.367972149512962), + const Offset(6.172793116155802, 21.823631861702058), + const Offset(7.363587976838016, 17.665129222832853), + const Offset(11.400806749308899, 11.800457098273661), + const Offset(17.41878573585796, 8.03287301910486), + const Offset(24.257523532175192, 6.996159828679087), + const Offset(29.90338248135665, 8.291042849526), + const Offset(33.76252909490214, 10.56619705548221), + const Offset(36.23501636298456, 12.973675163618006), + const Offset(37.77053540180521, 15.158665125787222), + const Offset(38.70420448893307, 17.008159945496722), + const Offset(39.260392038988186, 18.5104805430827), + const Offset(39.58393261852967, 19.691668944482075), + const Offset(39.766765502294305, 20.58840471665747), + const Offset(39.866421084642994, 21.237322746452932), + const Offset(39.91802804639694, 21.671102155152063), + const Offset(39.94204075298555, 21.917555098992118), + const Offset(39.94920417650143, 21.999827480806236), + const Offset(39.94921875, 22.0), + ], + const [ + const Offset(6.0, 26.0), + const Offset(5.976562557689849, 25.638185989482512), + const Offset(5.951781669661045, 24.367972149512962), + const Offset(6.172793116155802, 21.823631861702058), + const Offset(7.363587976838016, 17.665129222832853), + const Offset(11.400806749308899, 11.800457098273661), + const Offset(17.41878573585796, 8.03287301910486), + const Offset(24.257523532175192, 6.996159828679087), + const Offset(29.90338248135665, 8.291042849526), + const Offset(33.76252909490214, 10.56619705548221), + const Offset(36.23501636298456, 12.973675163618006), + const Offset(37.77053540180521, 15.158665125787222), + const Offset(38.70420448893307, 17.008159945496722), + const Offset(39.260392038988186, 18.5104805430827), + const Offset(39.58393261852967, 19.691668944482075), + const Offset(39.766765502294305, 20.58840471665747), + const Offset(39.866421084642994, 21.237322746452932), + const Offset(39.91802804639694, 21.671102155152063), + const Offset(39.94204075298555, 21.917555098992118), + const Offset(39.94920417650143, 21.999827480806236), + const Offset(39.94921875, 22.0), + ], + ), + const _PathClose( + ), + ], + ), + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(6.0, 36.0), + const Offset(5.8396336833594695, 35.66398057820908), + const Offset(5.329309336374063, 34.47365089829387), + const Offset(4.546341863759643, 32.03857491308836), + const Offset(3.9472816617934896, 27.893335303194206), + const Offset(4.788314785722232, 21.470485758169694), + const Offset(7.406922551234356, 16.186721598040453), + const Offset(10.987511722222681, 12.449414121983239), + const Offset(14.290737577882037, 10.382465570533384), + const Offset(16.84152025666389, 9.340052761292668), + const Offset(18.753361861843203, 8.79207829497377), + const Offset(20.19495897321279, 8.483469022255434), + const Offset(21.293826339887335, 8.297708512391797), + const Offset(22.135385178177998, 8.180000583359465), + const Offset(22.776244370552647, 8.102975309903787), + const Offset(23.25488929254563, 8.051973096906334), + const Offset(23.598629725699347, 8.018606137477462), + const Offset(23.827700643867974, 7.99783596371886), + const Offset(23.95771797811348, 7.986559676107813), + const Offset(24.001111438945117, 7.982878122631195), + const Offset(24.001202429357242, 7.98287044589657), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 36.0), + const Offset(5.8396336833594695, 35.66398057820908), + const Offset(5.329309336374063, 34.47365089829387), + const Offset(4.546341863759643, 32.03857491308836), + const Offset(3.9472816617934896, 27.893335303194206), + const Offset(4.788314785722232, 21.470485758169694), + const Offset(7.406922551234356, 16.186721598040453), + const Offset(10.987511722222681, 12.449414121983239), + const Offset(14.290737577882037, 10.382465570533384), + const Offset(16.84152025666389, 9.340052761292668), + const Offset(18.753361861843203, 8.79207829497377), + const Offset(20.19495897321279, 8.483469022255434), + const Offset(21.293826339887335, 8.297708512391797), + const Offset(22.135385178177998, 8.180000583359465), + const Offset(22.776244370552647, 8.102975309903787), + const Offset(23.25488929254563, 8.051973096906334), + const Offset(23.598629725699347, 8.018606137477462), + const Offset(23.827700643867974, 7.99783596371886), + const Offset(23.95771797811348, 7.986559676107813), + const Offset(24.001111438945117, 7.982878122631195), + const Offset(24.001202429357242, 7.98287044589657), + ], + const [ + const Offset(42.0, 36.0), + const Offset(41.7493389152824, 36.20520796529164), + const Offset(40.85819701033384, 36.89246335931071), + const Offset(39.01294315759756, 38.1256246432051), + const Offset(35.758514239960064, 39.76970128020763), + const Offset(30.180134511403956, 41.28645636464381), + const Offset(24.56603417073137, 41.32925393403815), + const Offset(19.271926095830622, 39.91690773672663), + const Offset(15.201959304751512, 37.5726832793895), + const Offset(12.456295622648877, 35.01429311055303), + const Offset(10.686459838185314, 32.608514843335385), + const Offset(9.579921816288039, 30.502293804851334), + const Offset(8.90802993167501, 28.734147272525124), + const Offset(8.513791284564158, 27.294928344333726), + const Offset(8.292240475325507, 26.156988797411067), + const Offset(8.174465865426919, 25.287693028463128), + const Offset(8.11616441641861, 24.655137447505503), + const Offset(8.089821190085125, 24.230473791307258), + const Offset(8.079382709319852, 23.988506993748523), + const Offset(8.076631388780909, 23.907616552409003), + const Offset(8.076626005900048, 23.907446869353766), + ], + const [ + const Offset(42.0, 36.0), + const Offset(41.7493389152824, 36.20520796529164), + const Offset(40.85819701033384, 36.89246335931071), + const Offset(39.01294315759756, 38.1256246432051), + const Offset(35.758514239960064, 39.76970128020763), + const Offset(30.180134511403956, 41.28645636464381), + const Offset(24.56603417073137, 41.32925393403815), + const Offset(19.271926095830622, 39.91690773672663), + const Offset(15.201959304751512, 37.5726832793895), + const Offset(12.456295622648877, 35.01429311055303), + const Offset(10.686459838185314, 32.608514843335385), + const Offset(9.579921816288039, 30.502293804851334), + const Offset(8.90802993167501, 28.734147272525124), + const Offset(8.513791284564158, 27.294928344333726), + const Offset(8.292240475325507, 26.156988797411067), + const Offset(8.174465865426919, 25.287693028463128), + const Offset(8.11616441641861, 24.655137447505503), + const Offset(8.089821190085125, 24.230473791307258), + const Offset(8.079382709319852, 23.988506993748523), + const Offset(8.076631388780909, 23.907616552409003), + const Offset(8.076626005900048, 23.907446869353766), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 36.0), + const Offset(41.7493389152824, 36.20520796529164), + const Offset(40.85819701033384, 36.89246335931071), + const Offset(39.01294315759756, 38.1256246432051), + const Offset(35.758514239960064, 39.76970128020763), + const Offset(30.180134511403956, 41.28645636464381), + const Offset(24.56603417073137, 41.32925393403815), + const Offset(19.271926095830622, 39.91690773672663), + const Offset(15.201959304751512, 37.5726832793895), + const Offset(12.456295622648877, 35.01429311055303), + const Offset(10.686459838185314, 32.608514843335385), + const Offset(9.579921816288039, 30.502293804851334), + const Offset(8.90802993167501, 28.734147272525124), + const Offset(8.513791284564158, 27.294928344333726), + const Offset(8.292240475325507, 26.156988797411067), + const Offset(8.174465865426919, 25.287693028463128), + const Offset(8.11616441641861, 24.655137447505503), + const Offset(8.089821190085125, 24.230473791307258), + const Offset(8.079382709319852, 23.988506993748523), + const Offset(8.076631388780909, 23.907616552409003), + const Offset(8.076626005900048, 23.907446869353766), + ], + const [ + const Offset(42.0, 32.0), + const Offset(41.803966700752746, 32.205577011286266), + const Offset(41.104447603276626, 32.89996903899956), + const Offset(39.64402995767152, 34.17517788052204), + const Offset(37.031973302731046, 35.97545970343111), + const Offset(32.44508133022271, 37.98012671725157), + const Offset(27.6644042246058, 38.77327245743646), + const Offset(22.963108117227325, 38.302914175295534), + const Offset(19.18039906547299, 36.862333955479784), + const Offset(16.509090720567585, 35.04434211490934), + const Offset(14.703380298498667, 33.21759365821649), + const Offset(13.512146444284534, 31.556733263561572), + const Offset(12.740174664860898, 30.12862517729895), + const Offset(12.248059307884624, 28.947244716051806), + const Offset(11.939734974297815, 28.002595790430043), + const Offset(11.750425410476474, 27.27521551305395), + const Offset(11.637314290474384, 26.742992599694542), + const Offset(11.572897732210654, 26.384358993735816), + const Offset(11.54031155133882, 26.17955109507089), + const Offset(11.530083003283234, 26.111009046369567), + const Offset(11.530061897030713, 26.110865227715482), + ], + const [ + const Offset(42.0, 32.0), + const Offset(41.803966700752746, 32.205577011286266), + const Offset(41.104447603276626, 32.89996903899956), + const Offset(39.64402995767152, 34.17517788052204), + const Offset(37.031973302731046, 35.97545970343111), + const Offset(32.44508133022271, 37.98012671725157), + const Offset(27.6644042246058, 38.77327245743646), + const Offset(22.963108117227325, 38.302914175295534), + const Offset(19.18039906547299, 36.862333955479784), + const Offset(16.509090720567585, 35.04434211490934), + const Offset(14.703380298498667, 33.21759365821649), + const Offset(13.512146444284534, 31.556733263561572), + const Offset(12.740174664860898, 30.12862517729895), + const Offset(12.248059307884624, 28.947244716051806), + const Offset(11.939734974297815, 28.002595790430043), + const Offset(11.750425410476474, 27.27521551305395), + const Offset(11.637314290474384, 26.742992599694542), + const Offset(11.572897732210654, 26.384358993735816), + const Offset(11.54031155133882, 26.17955109507089), + const Offset(11.530083003283234, 26.111009046369567), + const Offset(11.530061897030713, 26.110865227715482), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 32.0), + const Offset(41.803966700752746, 32.205577011286266), + const Offset(41.104447603276626, 32.89996903899956), + const Offset(39.64402995767152, 34.17517788052204), + const Offset(37.031973302731046, 35.97545970343111), + const Offset(32.44508133022271, 37.98012671725157), + const Offset(27.6644042246058, 38.77327245743646), + const Offset(22.963108117227325, 38.302914175295534), + const Offset(19.18039906547299, 36.862333955479784), + const Offset(16.509090720567585, 35.04434211490934), + const Offset(14.703380298498667, 33.21759365821649), + const Offset(13.512146444284534, 31.556733263561572), + const Offset(12.740174664860898, 30.12862517729895), + const Offset(12.248059307884624, 28.947244716051806), + const Offset(11.939734974297815, 28.002595790430043), + const Offset(11.750425410476474, 27.27521551305395), + const Offset(11.637314290474384, 26.742992599694542), + const Offset(11.572897732210654, 26.384358993735816), + const Offset(11.54031155133882, 26.17955109507089), + const Offset(11.530083003283234, 26.111009046369567), + const Offset(11.530061897030713, 26.110865227715482), + ], + const [ + const Offset(6.0, 32.0), + const Offset(5.899914425897517, 31.66443482499171), + const Offset(5.601001082666045, 30.482888615847468), + const Offset(5.242005036683729, 28.09953280239226), + const Offset(5.346316156571252, 24.145975901906155), + const Offset(7.249241148069178, 18.317100047682345), + const Offset(10.710823881370487, 13.931896549234073), + const Offset(14.817117889097364, 11.294374466111893), + const Offset(18.288493245756, 10.248489378687303), + const Offset(20.784419638077317, 10.013509863155594), + const Offset(22.541938014255397, 10.075312777589325), + const Offset(23.798109358346892, 10.220508832423288), + const Offset(24.71461203122786, 10.370924674281323), + const Offset(25.392890381083, 10.501349297587215), + const Offset(25.896277759611298, 10.60605174724228), + const Offset(26.265268043339944, 10.685909272436422), + const Offset(26.526795349038366, 10.74364670273436), + const Offset(26.699555102368272, 10.782158496973931), + const Offset(26.79709065296033, 10.80399872839147), + const Offset(26.829561509459538, 10.811282301423006), + const Offset(26.829629554119695, 10.811297570626497), + ], + const [ + const Offset(6.0, 32.0), + const Offset(5.899914425897517, 31.66443482499171), + const Offset(5.601001082666045, 30.482888615847468), + const Offset(5.242005036683729, 28.09953280239226), + const Offset(5.346316156571252, 24.145975901906155), + const Offset(7.249241148069178, 18.317100047682345), + const Offset(10.710823881370487, 13.931896549234073), + const Offset(14.817117889097364, 11.294374466111893), + const Offset(18.288493245756, 10.248489378687303), + const Offset(20.784419638077317, 10.013509863155594), + const Offset(22.541938014255397, 10.075312777589325), + const Offset(23.798109358346892, 10.220508832423288), + const Offset(24.71461203122786, 10.370924674281323), + const Offset(25.392890381083, 10.501349297587215), + const Offset(25.896277759611298, 10.60605174724228), + const Offset(26.265268043339944, 10.685909272436422), + const Offset(26.526795349038366, 10.74364670273436), + const Offset(26.699555102368272, 10.782158496973931), + const Offset(26.79709065296033, 10.80399872839147), + const Offset(26.829561509459538, 10.811282301423006), + const Offset(26.829629554119695, 10.811297570626497), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 32.0), + const Offset(5.899914425897517, 31.66443482499171), + const Offset(5.601001082666045, 30.482888615847468), + const Offset(5.242005036683729, 28.09953280239226), + const Offset(5.346316156571252, 24.145975901906155), + const Offset(7.249241148069178, 18.317100047682345), + const Offset(10.710823881370487, 13.931896549234073), + const Offset(14.817117889097364, 11.294374466111893), + const Offset(18.288493245756, 10.248489378687303), + const Offset(20.784419638077317, 10.013509863155594), + const Offset(22.541938014255397, 10.075312777589325), + const Offset(23.798109358346892, 10.220508832423288), + const Offset(24.71461203122786, 10.370924674281323), + const Offset(25.392890381083, 10.501349297587215), + const Offset(25.896277759611298, 10.60605174724228), + const Offset(26.265268043339944, 10.685909272436422), + const Offset(26.526795349038366, 10.74364670273436), + const Offset(26.699555102368272, 10.782158496973931), + const Offset(26.79709065296033, 10.80399872839147), + const Offset(26.829561509459538, 10.811282301423006), + const Offset(26.829629554119695, 10.811297570626497), + ], + const [ + const Offset(6.0, 36.0), + const Offset(5.839633683308566, 35.66398057820831), + const Offset(5.329309336323984, 34.47365089829046), + const Offset(4.546341863735712, 32.03857491308413), + const Offset(3.947281661825336, 27.893335303206097), + const Offset(4.788314785746671, 21.47048575818877), + const Offset(7.406922551270995, 16.18672159809414), + const Offset(10.98751172223972, 12.449414122039723), + const Offset(14.290737577881032, 10.382465570503403), + const Offset(16.841520256655304, 9.340052761342939), + const Offset(18.753361861827802, 8.792078295019234), + const Offset(20.194958973207576, 8.483469022266245), + const Offset(21.293826339889407, 8.297708512388375), + const Offset(22.13538517817335, 8.180000583365981), + const Offset(22.776244370563283, 8.102975309890528), + const Offset(23.25488929251534, 8.051973096940955), + const Offset(23.598629725644848, 8.018606137536025), + const Offset(23.82770064384222, 7.997835963745423), + const Offset(23.957717978081078, 7.986559676140466), + const Offset(24.001111438940168, 7.982878122636148), + const Offset(24.001202429373503, 7.982870445880305), + ], + const [ + const Offset(6.0, 36.0), + const Offset(5.839633683308566, 35.66398057820831), + const Offset(5.329309336323984, 34.47365089829046), + const Offset(4.546341863735712, 32.03857491308413), + const Offset(3.947281661825336, 27.893335303206097), + const Offset(4.788314785746671, 21.47048575818877), + const Offset(7.406922551270995, 16.18672159809414), + const Offset(10.98751172223972, 12.449414122039723), + const Offset(14.290737577881032, 10.382465570503403), + const Offset(16.841520256655304, 9.340052761342939), + const Offset(18.753361861827802, 8.792078295019234), + const Offset(20.194958973207576, 8.483469022266245), + const Offset(21.293826339889407, 8.297708512388375), + const Offset(22.13538517817335, 8.180000583365981), + const Offset(22.776244370563283, 8.102975309890528), + const Offset(23.25488929251534, 8.051973096940955), + const Offset(23.598629725644848, 8.018606137536025), + const Offset(23.82770064384222, 7.997835963745423), + const Offset(23.957717978081078, 7.986559676140466), + const Offset(24.001111438940168, 7.982878122636148), + const Offset(24.001202429373503, 7.982870445880305), + ], + ), + const _PathClose( + ), + ], + ), + const _PathFrames( + opacities: const [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + ], + commands: const <_PathCommand>[ + const _PathMoveTo( + const [ + const Offset(6.0, 16.0), + const Offset(6.222470088677106, 15.614531066984553), + const Offset(7.071161725316092, 14.306422712262563), + const Offset(9.085869786142727, 11.907139949336411), + const Offset(13.311519331212619, 8.711520321213257), + const Offset(21.694206315186374, 6.462423500731354), + const Offset(30.07031570748504, 8.471955170698632), + const Offset(36.20036889900587, 14.155750775196541), + const Offset(38.533897479983715, 20.76099122996903), + const Offset(38.182626701431914, 26.194302454359914), + const Offset(36.59711302702814, 30.110286603895076), + const Offset(34.63761335058528, 32.76106836363335), + const Offset(32.7272901891386, 34.4927008221791), + const Offset(31.04869117038896, 35.596105690451935), + const Offset(29.664526028757855, 36.28441549314729), + const Offset(28.581655311555835, 36.70452225851578), + const Offset(27.782897949107628, 36.95396775456513), + const Offset(27.242531133855476, 37.09522522130338), + const Offset(26.933380541033216, 37.166375518103024), + const Offset(26.82984682779076, 37.188656481991416), + const Offset(26.829629554103434, 37.18870242935725), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 16.0), + const Offset(6.222470088677106, 15.614531066984553), + const Offset(7.071161725316092, 14.306422712262563), + const Offset(9.085869786142727, 11.907139949336411), + const Offset(13.311519331212619, 8.711520321213257), + const Offset(21.694206315186374, 6.462423500731354), + const Offset(30.07031570748504, 8.471955170698632), + const Offset(36.20036889900587, 14.155750775196541), + const Offset(38.533897479983715, 20.76099122996903), + const Offset(38.182626701431914, 26.194302454359914), + const Offset(36.59711302702814, 30.110286603895076), + const Offset(34.63761335058528, 32.76106836363335), + const Offset(32.7272901891386, 34.4927008221791), + const Offset(31.04869117038896, 35.596105690451935), + const Offset(29.664526028757855, 36.28441549314729), + const Offset(28.581655311555835, 36.70452225851578), + const Offset(27.782897949107628, 36.95396775456513), + const Offset(27.242531133855476, 37.09522522130338), + const Offset(26.933380541033216, 37.166375518103024), + const Offset(26.82984682779076, 37.188656481991416), + const Offset(26.829629554103434, 37.18870242935725), + ], + const [ + const Offset(42.0, 16.0), + const Offset(42.119273441095075, 16.516374018071716), + const Offset(42.428662704565184, 18.32937541467259), + const Offset(42.54812490043565, 21.94159775950881), + const Offset(41.3111285319893, 27.683594454682137), + const Offset(36.06395079582478, 35.01020271691918), + const Offset(28.59459512599702, 38.51093769070532), + const Offset(21.239886122259133, 38.07233071493643), + const Offset(16.251628495692138, 35.34156866251391), + const Offset(13.527101819238178, 32.27103394597236), + const Offset(12.16858814546228, 29.604397296366464), + const Offset(11.548946515009288, 27.474331231158473), + const Offset(11.311114637013635, 25.826563435488687), + const Offset(11.262012546535352, 24.572239162454554), + const Offset(11.298221100690522, 23.63118177535833), + const Offset(11.364474416879979, 22.940254245947138), + const Offset(11.431638843687892, 22.451805922237554), + const Offset(11.485090012547001, 22.130328573710905), + const Offset(11.518417313485447, 21.949395273355513), + const Offset(11.530012405933167, 21.889264075838188), + const Offset(11.53003696527787, 21.889138124802937), + ], + const [ + const Offset(42.0, 16.0), + const Offset(42.119273441095075, 16.516374018071716), + const Offset(42.428662704565184, 18.32937541467259), + const Offset(42.54812490043565, 21.94159775950881), + const Offset(41.3111285319893, 27.683594454682137), + const Offset(36.06395079582478, 35.01020271691918), + const Offset(28.59459512599702, 38.51093769070532), + const Offset(21.239886122259133, 38.07233071493643), + const Offset(16.251628495692138, 35.34156866251391), + const Offset(13.527101819238178, 32.27103394597236), + const Offset(12.16858814546228, 29.604397296366464), + const Offset(11.548946515009288, 27.474331231158473), + const Offset(11.311114637013635, 25.826563435488687), + const Offset(11.262012546535352, 24.572239162454554), + const Offset(11.298221100690522, 23.63118177535833), + const Offset(11.364474416879979, 22.940254245947138), + const Offset(11.431638843687892, 22.451805922237554), + const Offset(11.485090012547001, 22.130328573710905), + const Offset(11.518417313485447, 21.949395273355513), + const Offset(11.530012405933167, 21.889264075838188), + const Offset(11.53003696527787, 21.889138124802937), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 16.0), + const Offset(42.119273441095075, 16.516374018071716), + const Offset(42.428662704565184, 18.32937541467259), + const Offset(42.54812490043565, 21.94159775950881), + const Offset(41.3111285319893, 27.683594454682137), + const Offset(36.06395079582478, 35.01020271691918), + const Offset(28.59459512599702, 38.51093769070532), + const Offset(21.239886122259133, 38.07233071493643), + const Offset(16.251628495692138, 35.34156866251391), + const Offset(13.527101819238178, 32.27103394597236), + const Offset(12.16858814546228, 29.604397296366464), + const Offset(11.548946515009288, 27.474331231158473), + const Offset(11.311114637013635, 25.826563435488687), + const Offset(11.262012546535352, 24.572239162454554), + const Offset(11.298221100690522, 23.63118177535833), + const Offset(11.364474416879979, 22.940254245947138), + const Offset(11.431638843687892, 22.451805922237554), + const Offset(11.485090012547001, 22.130328573710905), + const Offset(11.518417313485447, 21.949395273355513), + const Offset(11.530012405933167, 21.889264075838188), + const Offset(11.53003696527787, 21.889138124802937), + ], + const [ + const Offset(42.0, 12.0), + const Offset(42.22538630246601, 12.517777761542249), + const Offset(42.90619853384615, 14.357900907446863), + const Offset(43.759884509852945, 18.128995147835514), + const Offset(43.66585885175813, 24.44736028078141), + const Offset(39.74861752085834, 33.43380529842439), + const Offset(32.57188683977151, 39.07136996422343), + const Offset(24.376857043988256, 40.600018479197814), + const Offset(17.959269400168804, 39.004426856660785), + const Offset(13.850567169499653, 36.311009998593796), + const Offset(11.374155956344177, 33.58880277176081), + const Offset(9.917496515696001, 31.204288894581083), + const Offset(9.07498759074148, 29.236785710939074), + const Offset(8.597571742452605, 27.666692096657314), + const Offset(8.334783321442917, 26.44693980672826), + const Offset(8.195874559699876, 25.52824222288586), + const Offset(8.126295299747222, 24.866824239052814), + const Offset(8.093843447379264, 24.426077640310794), + const Offset(8.080338503727083, 24.17611706018137), + const Offset(8.076619249177135, 24.092742069165425), + const Offset(8.07661186374038, 24.09256727275783), + ], + const [ + const Offset(42.0, 12.0), + const Offset(42.22538630246601, 12.517777761542249), + const Offset(42.90619853384615, 14.357900907446863), + const Offset(43.759884509852945, 18.128995147835514), + const Offset(43.66585885175813, 24.44736028078141), + const Offset(39.74861752085834, 33.43380529842439), + const Offset(32.57188683977151, 39.07136996422343), + const Offset(24.376857043988256, 40.600018479197814), + const Offset(17.959269400168804, 39.004426856660785), + const Offset(13.850567169499653, 36.311009998593796), + const Offset(11.374155956344177, 33.58880277176081), + const Offset(9.917496515696001, 31.204288894581083), + const Offset(9.07498759074148, 29.236785710939074), + const Offset(8.597571742452605, 27.666692096657314), + const Offset(8.334783321442917, 26.44693980672826), + const Offset(8.195874559699876, 25.52824222288586), + const Offset(8.126295299747222, 24.866824239052814), + const Offset(8.093843447379264, 24.426077640310794), + const Offset(8.080338503727083, 24.17611706018137), + const Offset(8.076619249177135, 24.092742069165425), + const Offset(8.07661186374038, 24.09256727275783), + ], + ), + const _PathCubicTo( + const [ + const Offset(42.0, 12.0), + const Offset(42.22538630246601, 12.517777761542249), + const Offset(42.90619853384615, 14.357900907446863), + const Offset(43.759884509852945, 18.128995147835514), + const Offset(43.66585885175813, 24.44736028078141), + const Offset(39.74861752085834, 33.43380529842439), + const Offset(32.57188683977151, 39.07136996422343), + const Offset(24.376857043988256, 40.600018479197814), + const Offset(17.959269400168804, 39.004426856660785), + const Offset(13.850567169499653, 36.311009998593796), + const Offset(11.374155956344177, 33.58880277176081), + const Offset(9.917496515696001, 31.204288894581083), + const Offset(9.07498759074148, 29.236785710939074), + const Offset(8.597571742452605, 27.666692096657314), + const Offset(8.334783321442917, 26.44693980672826), + const Offset(8.195874559699876, 25.52824222288586), + const Offset(8.126295299747222, 24.866824239052814), + const Offset(8.093843447379264, 24.426077640310794), + const Offset(8.080338503727083, 24.17611706018137), + const Offset(8.076619249177135, 24.092742069165425), + const Offset(8.07661186374038, 24.09256727275783), + ], + const [ + const Offset(6.0, 12.0), + const Offset(6.3229312318803075, 11.61579282114921), + const Offset(7.523361420980265, 10.332065476778915), + const Offset(10.234818160108134, 8.075701885898315), + const Offset(15.555284551985588, 5.400098023461183), + const Offset(25.267103519984172, 4.663978182144188), + const Offset(34.065497532306516, 8.668225867992323), + const Offset(39.59155761731576, 16.27703318845691), + const Offset(40.72409454498984, 24.108085016590273), + const Offset(39.139841854472834, 30.0780814324673), + const Offset(36.514293313228855, 34.10942912386185), + const Offset(33.744815583253256, 36.6601595585975), + const Offset(31.226861893018718, 38.20062678263231), + const Offset(29.10189988007002, 39.09038725780428), + const Offset(27.3951953205187, 39.57837027981981), + const Offset(26.083922435637483, 39.82883505984612), + const Offset(25.128742795932077, 39.94653528477588), + const Offset(24.487982707377697, 39.99564983955995), + const Offset(24.123290412440365, 40.013021521592925), + const Offset(24.001457946431486, 40.017121849607435), + const Offset(24.001202429333205, 40.017129554079396), + ], + const [ + const Offset(6.0, 12.0), + const Offset(6.3229312318803075, 11.61579282114921), + const Offset(7.523361420980265, 10.332065476778915), + const Offset(10.234818160108134, 8.075701885898315), + const Offset(15.555284551985588, 5.400098023461183), + const Offset(25.267103519984172, 4.663978182144188), + const Offset(34.065497532306516, 8.668225867992323), + const Offset(39.59155761731576, 16.27703318845691), + const Offset(40.72409454498984, 24.108085016590273), + const Offset(39.139841854472834, 30.0780814324673), + const Offset(36.514293313228855, 34.10942912386185), + const Offset(33.744815583253256, 36.6601595585975), + const Offset(31.226861893018718, 38.20062678263231), + const Offset(29.10189988007002, 39.09038725780428), + const Offset(27.3951953205187, 39.57837027981981), + const Offset(26.083922435637483, 39.82883505984612), + const Offset(25.128742795932077, 39.94653528477588), + const Offset(24.487982707377697, 39.99564983955995), + const Offset(24.123290412440365, 40.013021521592925), + const Offset(24.001457946431486, 40.017121849607435), + const Offset(24.001202429333205, 40.017129554079396), + ], + ), + const _PathCubicTo( + const [ + const Offset(6.0, 12.0), + const Offset(6.3229312318803075, 11.61579282114921), + const Offset(7.523361420980265, 10.332065476778915), + const Offset(10.234818160108134, 8.075701885898315), + const Offset(15.555284551985588, 5.400098023461183), + const Offset(25.267103519984172, 4.663978182144188), + const Offset(34.065497532306516, 8.668225867992323), + const Offset(39.59155761731576, 16.27703318845691), + const Offset(40.72409454498984, 24.108085016590273), + const Offset(39.139841854472834, 30.0780814324673), + const Offset(36.514293313228855, 34.10942912386185), + const Offset(33.744815583253256, 36.6601595585975), + const Offset(31.226861893018718, 38.20062678263231), + const Offset(29.10189988007002, 39.09038725780428), + const Offset(27.3951953205187, 39.57837027981981), + const Offset(26.083922435637483, 39.82883505984612), + const Offset(25.128742795932077, 39.94653528477588), + const Offset(24.487982707377697, 39.99564983955995), + const Offset(24.123290412440365, 40.013021521592925), + const Offset(24.001457946431486, 40.017121849607435), + const Offset(24.001202429333205, 40.017129554079396), + ], + const [ + const Offset(6.0, 16.0), + const Offset(6.22247008872931, 15.614531066985863), + const Offset(7.071161725356028, 14.306422712267109), + const Offset(9.085869786222908, 11.907139949360454), + const Offset(13.311519331206826, 8.711520321209331), + const Offset(21.69420631520211, 6.462423500762615), + const Offset(30.070315707485825, 8.471955170682651), + const Offset(36.20036889903345, 14.155750775152455), + const Offset(38.53389748002304, 20.760991229943293), + const Offset(38.18262670145813, 26.194302454353455), + const Offset(36.597113027065134, 30.110286603895844), + const Offset(34.63761335066132, 32.761068363650764), + const Offset(32.72729018913396, 34.49270082217723), + const Offset(31.048691170407302, 35.59610569046216), + const Offset(29.66452602881138, 36.28441549318417), + const Offset(28.58165531160348, 36.70452225855387), + const Offset(27.78289794916673, 36.95396775461755), + const Offset(27.24253113386635, 37.09522522131371), + const Offset(26.933380541051008, 37.16637551812059), + const Offset(26.829846827821875, 37.18865648202253), + const Offset(26.829629554079393, 37.188702429333205), + ], + const [ + const Offset(6.0, 16.0), + const Offset(6.22247008872931, 15.614531066985863), + const Offset(7.071161725356028, 14.306422712267109), + const Offset(9.085869786222908, 11.907139949360454), + const Offset(13.311519331206826, 8.711520321209331), + const Offset(21.69420631520211, 6.462423500762615), + const Offset(30.070315707485825, 8.471955170682651), + const Offset(36.20036889903345, 14.155750775152455), + const Offset(38.53389748002304, 20.760991229943293), + const Offset(38.18262670145813, 26.194302454353455), + const Offset(36.597113027065134, 30.110286603895844), + const Offset(34.63761335066132, 32.761068363650764), + const Offset(32.72729018913396, 34.49270082217723), + const Offset(31.048691170407302, 35.59610569046216), + const Offset(29.66452602881138, 36.28441549318417), + const Offset(28.58165531160348, 36.70452225855387), + const Offset(27.78289794916673, 36.95396775461755), + const Offset(27.24253113386635, 37.09522522131371), + const Offset(26.933380541051008, 37.16637551812059), + const Offset(26.829846827821875, 37.18865648202253), + const Offset(26.829629554079393, 37.188702429333205), + ], + ), + const _PathClose( + ), + ], + ), + ], + matchTextDirection: true, +); diff --git a/packages/flutter/lib/src/widgets/icon.dart b/packages/flutter/lib/src/widgets/icon.dart index 1149847b07..6529406565 100644 --- a/packages/flutter/lib/src/widgets/icon.dart +++ b/packages/flutter/lib/src/widgets/icon.dart @@ -66,11 +66,13 @@ class Icon extends StatelessWidget { /// The given color will be adjusted by the opacity of the current /// [IconTheme], if any. /// - /// If no [IconTheme]s are specified, icons will default to black. /// /// In material apps, if there is a [Theme] without any [IconTheme]s /// specified, icon colors default to white if the theme is dark /// and black if the theme is light. + /// + /// If no [IconTheme] and no [Theme] is specified, icons will default to black. + /// /// See [Theme] to set the current theme and [ThemeData.brightness] /// for setting the current theme's brightness. /// @@ -86,7 +88,7 @@ class Icon extends StatelessWidget { /// Semantic label for the icon. /// - /// This would be read out in accessibility modes (e.g TalkBack/VoiceOver). + /// Announced in accessibility modes (e.g TalkBack/VoiceOver). /// This label does not show in the UI. /// /// See also: diff --git a/packages/flutter/test/material_animated_icons/animated_icons_private_test.dart b/packages/flutter/test/material_animated_icons/animated_icons_private_test.dart new file mode 100644 index 0000000000..3a9d4cdfa8 --- /dev/null +++ b/packages/flutter/test/material_animated_icons/animated_icons_private_test.dart @@ -0,0 +1,408 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is the test for the private implementation of animated icons. +// To make the private API accessible from the test we do not import the +// material material_animated_icons library, but instead, this test file is an +// implementation of that library, using some of the parts of the real +// material_animated_icons, this give the test access to the private APIs. +library material_animated_icons; + +import 'dart:math' as math show pi; +import 'dart:ui' show lerpDouble; +import 'dart:ui' as ui show Paint, Path, Canvas; + +import 'package:flutter/animation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; + +part '../../lib/src/material_animated_icons/animated_icons.dart'; +part '../../lib/src/material_animated_icons/animated_icons_data.dart'; +part '../../lib/src/material_animated_icons/data/menu_arrow.g.dart'; + +class MockCanvas extends Mock implements ui.Canvas {} +class MockPath extends Mock implements ui.Path {} + +void main () { + group('Interpolate points', () { + test('- single point', () { + final List points = const [ + const Offset(25.0, 1.0), + ]; + expect(_interpolate(points, 0.0, Offset.lerp), const Offset(25.0, 1.0)); + expect(_interpolate(points, 0.5, Offset.lerp), const Offset(25.0, 1.0)); + expect(_interpolate(points, 1.0, Offset.lerp), const Offset(25.0, 1.0)); + }); + + test('- two points', () { + final List points = const [ + const Offset(25.0, 1.0), + const Offset(12.0, 12.0), + ]; + expect(_interpolate(points, 0.0, Offset.lerp), const Offset(25.0, 1.0)); + expect(_interpolate(points, 0.5, Offset.lerp), const Offset(18.5, 6.5)); + expect(_interpolate(points, 1.0, Offset.lerp), const Offset(12.0, 12.0)); + }); + + test('- three points', () { + final List points = const [ + const Offset(25.0, 1.0), + const Offset(12.0, 12.0), + const Offset(23.0, 9.0), + ]; + expect(_interpolate(points, 0.0, Offset.lerp), const Offset(25.0, 1.0)); + expect(_interpolate(points, 0.25, Offset.lerp), const Offset(18.5, 6.5)); + expect(_interpolate(points, 0.5, Offset.lerp), const Offset(12.0, 12.0)); + expect(_interpolate(points, 0.75, Offset.lerp), const Offset(17.5, 10.5)); + expect(_interpolate(points, 1.0, Offset.lerp), const Offset(23.0, 9.0)); + }); + }); + + group('_AnimatedIconPainter', () { + final Size size = const Size(48.0, 48.0); + final MockCanvas mockCanvas = new MockCanvas(); + List generatedPaths; + final _UiPathFactory pathFactory = () { + final MockPath path = new MockPath(); + generatedPaths.add(path); + return path; + }; + + setUp(() { + generatedPaths = []; + }); + + test('progress 0', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 0.0), + generatedPaths[0].lineTo(48.0, 0.0), + generatedPaths[0].lineTo(48.0, 10.0), + generatedPaths[0].lineTo(0.0, 10.0), + generatedPaths[0].lineTo(0.0, 0.0), + generatedPaths[0].close(), + ]); + }); + + test('progress 1', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(1.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 38.0), + generatedPaths[0].lineTo(48.0, 38.0), + generatedPaths[0].lineTo(48.0, 48.0), + generatedPaths[0].lineTo(0.0, 48.0), + generatedPaths[0].lineTo(0.0, 38.0), + generatedPaths[0].close(), + ]); + }); + + test('clamped progress', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(1.5), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 38.0), + generatedPaths[0].lineTo(48.0, 38.0), + generatedPaths[0].lineTo(48.0, 48.0), + generatedPaths[0].lineTo(0.0, 48.0), + generatedPaths[0].lineTo(0.0, 38.0), + generatedPaths[0].close(), + ]); + }); + + test('scale', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 0.5, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + verify(mockCanvas.scale(0.5, 0.5)); + }); + + test('mirror', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: true, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + verifyInOrder([ + mockCanvas.rotate(math.pi), + mockCanvas.translate(-48.0, -48.0) + ]); + }); + + test('interpolated frame', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: movingBar.paths, + progress: const AlwaysStoppedAnimation(0.5), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 19.0), + generatedPaths[0].lineTo(48.0, 19.0), + generatedPaths[0].lineTo(48.0, 29.0), + generatedPaths[0].lineTo(0.0, 29.0), + generatedPaths[0].lineTo(0.0, 19.0), + generatedPaths[0].close(), + ]); + }); + + test('curved frame', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(1.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 24.0), + generatedPaths[0].cubicTo(16.0, 48.0, 32.0, 48.0, 48.0, 24.0), + generatedPaths[0].lineTo(0.0, 24.0), + generatedPaths[0].close(), + ]); + }); + + test('interpolated curved frame', () { + final _AnimatedIconPainter painter = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.25), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + painter.paint(mockCanvas, size); + expect(generatedPaths.length, 1); + + verifyInOrder([ + generatedPaths[0].moveTo(0.0, 24.0), + generatedPaths[0].cubicTo(16.0, 17.0, 32.0, 17.0, 48.0, 24.0), + generatedPaths[0].lineTo(0.0, 24.0), + generatedPaths[0].close(), + ]); + }); + + test('should not repaint same values', () { + final _AnimatedIconPainter painter1 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + final _AnimatedIconPainter painter2 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + expect(painter1.shouldRepaint(painter2), false); + }); + + test('should repaint on progress change', () { + final _AnimatedIconPainter painter1 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + final _AnimatedIconPainter painter2 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.1), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + expect(painter1.shouldRepaint(painter2), true); + }); + + test('should repaint on color change', () { + final _AnimatedIconPainter painter1 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF00FF00), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + final _AnimatedIconPainter painter2 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFFFF0000), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + expect(painter1.shouldRepaint(painter2), true); + }); + + test('should repaint on paths change', () { + final _AnimatedIconPainter painter1 = new _AnimatedIconPainter( + paths: bow.paths, + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF0000FF), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + final _AnimatedIconPainter painter2 = new _AnimatedIconPainter( + paths: const <_PathFrames> [], + progress: const AlwaysStoppedAnimation(0.0), + color: const Color(0xFF0000FF), + scale: 1.0, + shouldMirror: false, + uiPathFactory: pathFactory + ); + + expect(painter1.shouldRepaint(painter2), true); + }); + + }); +} + +const _AnimatedIconData movingBar = const _AnimatedIconData( + const Size(48.0, 48.0), + const <_PathFrames> [ + const _PathFrames( + opacities: const [1.0, 0.2], + commands: const <_PathCommand> [ + const _PathMoveTo( + const [ + const Offset(0.0, 0.0), + const Offset(0.0, 38.0), + ], + ), + const _PathLineTo( + const [ + const Offset(48.0, 0.0), + const Offset(48.0, 38.0), + ], + ), + const _PathLineTo( + const [ + const Offset(48.0, 10.0), + const Offset(48.0, 48.0), + ], + ), + const _PathLineTo( + const [ + const Offset(0.0, 10.0), + const Offset(0.0, 48.0), + ], + ), + const _PathLineTo( + const [ + const Offset(0.0, 0.0), + const Offset(0.0, 38.0), + ], + ), + const _PathClose(), + ], + ), + ], +); + +const _AnimatedIconData bow = const _AnimatedIconData( + const Size(48.0, 48.0), + const <_PathFrames> [ + const _PathFrames( + opacities: const [1.0, 1.0], + commands: const <_PathCommand> [ + const _PathMoveTo( + const [ + const Offset(0.0, 24.0), + const Offset(0.0, 24.0), + const Offset(0.0, 24.0), + ], + ), + const _PathCubicTo( + const [ + const Offset(16.0, 24.0), + const Offset(16.0, 10.0), + const Offset(16.0, 48.0), + ], + const [ + const Offset(32.0, 24.0), + const Offset(32.0, 10.0), + const Offset(32.0, 48.0), + ], + const [ + const Offset(48.0, 24.0), + const Offset(48.0, 24.0), + const Offset(48.0, 24.0), + ], + ), + const _PathLineTo( + const [ + const Offset(0.0, 24.0), + const Offset(0.0, 24.0), + const Offset(0.0, 24.0), + ], + ), + const _PathClose(), + ], + ), + ], +); diff --git a/packages/flutter/test/material_animated_icons/animated_icons_test.dart b/packages/flutter/test/material_animated_icons/animated_icons_test.dart new file mode 100644 index 0000000000..e556bbd4cc --- /dev/null +++ b/packages/flutter/test/material_animated_icons/animated_icons_test.dart @@ -0,0 +1,237 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:math' as math show pi; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/material_animated_icons.dart'; +import 'package:mockito/mockito.dart'; + +import '../widgets/semantics_tester.dart'; + +class MockCanvas extends Mock implements Canvas {} + +void main() { + testWidgets('IconTheme color', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verify(canvas.drawPath(any, paintColorMatcher(0xFF666666))); + }); + + testWidgets('IconTheme opacity', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + opacity: 0.5, + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verify(canvas.drawPath(any, paintColorMatcher(0x80666666))); + }); + + testWidgets('color overrides IconTheme color', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + color: const Color(0xFF0000FF), + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verify(canvas.drawPath(any, paintColorMatcher(0xFF0000FF))); + }); + + testWidgets('IconTheme size', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + size: 12.0, + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(12.0, 12.0)); + // arrow_menu default size is 48x48 so we expect it to be scaled by 0.25. + verify(canvas.scale(0.25, 0.25)); + }); + + testWidgets('size overridesIconTheme size', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + size: 12.0, + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + size: 96.0, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(12.0, 12.0)); + // arrow_menu default size is 48x48 so we expect it to be scaled by 2. + verify(canvas.scale(2.0, 2.0)); + }); + + testWidgets('Semantic label', (WidgetTester tester) async { + final SemanticsTester semantics = new SemanticsTester(tester); + + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + size: 96.0, + semanticLabel: 'a label', + ), + ), + ); + + expect(semantics, includesNodeWith(label: 'a label')); + }); + + testWidgets('Inherited text direction rtl', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.rtl, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verifyInOrder([ + canvas.rotate(math.pi), + canvas.translate(-48.0, -48.0) + ]); + }); + + testWidgets('Inherited text direction ltr', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verifyNever(canvas.rotate(any)); + verifyNever(canvas.translate(any, any)); + }); + + testWidgets('Inherited text direction overridden', (WidgetTester tester) async { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: const IconTheme( + data: const IconThemeData( + color: const Color(0xFF666666), + ), + child: const AnimatedIcon( + progress: const AlwaysStoppedAnimation(0.0), + icon: AnimatedIcons.arrow_menu, + textDirection: TextDirection.rtl, + ) + ), + ), + ); + final CustomPaint customPaint = tester.widget(find.byType(CustomPaint)); + final MockCanvas canvas = new MockCanvas(); + customPaint.painter.paint(canvas, const Size(48.0, 48.0)); + verifyInOrder([ + canvas.rotate(math.pi), + canvas.translate(-48.0, -48.0) + ]); + }); +} + +dynamic paintColorMatcher(int color) { + return new PaintColorMatcher(color); +} + +class PaintColorMatcher extends Matcher { + const PaintColorMatcher(this.expectedColor); + + final int expectedColor; + + @override + Description describe(Description description) => + description.add('color was not $expectedColor'); + + @override + bool matches(dynamic item, Map matchState) { + final Paint actualPaint = item; + return actualPaint.color == new Color(expectedColor); + } +}