From a42c76620175a949665f63bef671697160a78b54 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 30 Jul 2018 10:48:51 -0400 Subject: [PATCH 01/28] initial commit --- third_party/packages/path_parsing/.gitignore | 10 + .../packages/path_parsing/CHANGELOG.md | 3 + third_party/packages/path_parsing/LICENSE | 19 + third_party/packages/path_parsing/README.md | 5 + .../path_parsing/analysis_options.yaml | 152 ++++ .../path_parsing/lib/path_parsing.dart | 1 + .../path_parsing/lib/src/path_parsing.dart | 743 ++++++++++++++++++ .../lib/src/path_segment_type.dart | 233 ++++++ .../packages/path_parsing/pubspec.lock | 355 +++++++++ .../packages/path_parsing/pubspec.yaml | 17 + .../path_parsing/test/parse_path_test.dart | 220 ++++++ 11 files changed, 1758 insertions(+) create mode 100644 third_party/packages/path_parsing/.gitignore create mode 100644 third_party/packages/path_parsing/CHANGELOG.md create mode 100644 third_party/packages/path_parsing/LICENSE create mode 100644 third_party/packages/path_parsing/README.md create mode 100644 third_party/packages/path_parsing/analysis_options.yaml create mode 100644 third_party/packages/path_parsing/lib/path_parsing.dart create mode 100644 third_party/packages/path_parsing/lib/src/path_parsing.dart create mode 100644 third_party/packages/path_parsing/lib/src/path_segment_type.dart create mode 100644 third_party/packages/path_parsing/pubspec.lock create mode 100644 third_party/packages/path_parsing/pubspec.yaml create mode 100644 third_party/packages/path_parsing/test/parse_path_test.dart diff --git a/third_party/packages/path_parsing/.gitignore b/third_party/packages/path_parsing/.gitignore new file mode 100644 index 00000000000..43b5f446e6e --- /dev/null +++ b/third_party/packages/path_parsing/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ +.idea/ + +build/ + +.flutter-plugins diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md new file mode 100644 index 00000000000..f5e35ab237d --- /dev/null +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -0,0 +1,3 @@ +# CHANGELOG + +- 0.1.0: Initial release, based on the 0.2.4 release of path_drawing diff --git a/third_party/packages/path_parsing/LICENSE b/third_party/packages/path_parsing/LICENSE new file mode 100644 index 00000000000..246fd7b208c --- /dev/null +++ b/third_party/packages/path_parsing/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 Dan Field + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/packages/path_parsing/README.md b/third_party/packages/path_parsing/README.md new file mode 100644 index 00000000000..6088938d213 --- /dev/null +++ b/third_party/packages/path_parsing/README.md @@ -0,0 +1,5 @@ +# path_parsing + +Split from the Flutter path drawing library to create a pure Dart parsing +library for SVG paths and code generation (without dependencies on Flutter +runtime). \ No newline at end of file diff --git a/third_party/packages/path_parsing/analysis_options.yaml b/third_party/packages/path_parsing/analysis_options.yaml new file mode 100644 index 00000000000..486e3dbdd80 --- /dev/null +++ b/third_party/packages/path_parsing/analysis_options.yaml @@ -0,0 +1,152 @@ +# Specify analysis options. +# +# Until there are meta linter rules, each desired lint must be explicitly enabled. +# See: https://github.com/dart-lang/linter/issues/288 +# +# For a list of lints, see: http://dart-lang.github.io/linter/lints/ +# See the configuration guide for more +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer +# +# There are four similar analysis options files in the flutter repos: +# - analysis_options.yaml (this file) +# - packages/flutter/lib/analysis_options_user.yaml +# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml +# - https://github.com/flutter/engine/blob/master/analysis_options.yaml +# +# This file contains the analysis options used by Flutter tools, such as IntelliJ, +# Android Studio, and the `flutter analyze` command. +# +# The flutter/plugins repo contains a copy of this file, which should be kept +# in sync with this file. + +analyzer: + language: + enableSuperMixins: true + strong-mode: + implicit-dynamic: false + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: warning + # treat missing returns as a warning (not a hint) + missing_return: warning + # allow having TODOs in the code + todo: ignore + exclude: + # for Travis - don't try to analyze the flutter repo + - 'flutter/**' + + +linter: + rules: + # these rules are documented on and in the same order as + # the Dart Lint rules page to make maintenance easier + # https://github.com/dart-lang/linter/blob/master/example/all.yaml + - always_declare_return_types + - always_put_control_body_on_new_line + # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 + - always_require_non_null_named_parameters + - always_specify_types + - annotate_overrides + # - avoid_annotating_with_dynamic # conflicts with always_specify_types + - avoid_as + # - avoid_bool_literals_in_conditional_expressions # not yet tested + # - avoid_catches_without_on_clauses # we do this commonly + # - avoid_catching_errors # we do this commonly + - avoid_classes_with_only_static_members + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + # - avoid_positional_boolean_parameters # not yet tested + # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + # - avoid_returning_null # we do this commonly + # - avoid_returning_this # https://github.com/dart-lang/linter/issues/842 + # - avoid_setters_without_getters # not yet tested + # - avoid_single_cascade_in_expression_statements # not yet tested + - avoid_slow_async_io + # - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files + # - avoid_types_on_closure_parameters # conflicts with always_specify_types + # - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847 + - await_only_futures + - camel_case_types + - cancel_subscriptions + # - cascade_invocations # not yet tested + # - close_sinks # https://github.com/flutter/flutter/issues/5789 + # - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153 + # - constant_identifier_names # https://github.com/dart-lang/linter/issues/204 + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + # - invariant_booleans # https://github.com/flutter/flutter/issues/5790 + - iterable_contains_unrelated_type + # - join_return_with_assignment # not yet tested + - library_names + - library_prefixes + - list_remove_unrelated_type + # - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791 + - no_adjacent_strings_in_list + - no_duplicate_case_values + - non_constant_identifier_names + # - omit_local_variable_types # opposite of always_specify_types + # - one_member_abstracts # too many false positives + # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + # - parameter_assignments # we do this commonly + - prefer_adjacent_string_concatenation + - prefer_asserts_in_initializer_lists + - prefer_bool_in_asserts + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_const_constructors_in_immutables + - prefer_const_declarations + - prefer_const_literals_to_create_immutables + # - prefer_constructors_over_static_methods # not yet tested + - prefer_contains + # - prefer_equal_for_default_values # not yet tested + # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods + - prefer_final_fields + - prefer_final_locals + - prefer_foreach + # - prefer_function_declarations_over_variables # not yet tested + - prefer_initializing_formals + # - prefer_interpolation_to_compose_strings # not yet tested + - prefer_is_empty + - prefer_is_not_empty + - prefer_single_quotes + - prefer_typing_uninitialized_variables + - recursive_getters + - slash_for_doc_comments + - sort_constructors_first + - sort_unnamed_constructors_first + - super_goes_last + - test_types_in_equals + - throw_in_finally + # - type_annotate_public_apis # subset of always_specify_types + - type_init_formals + # - unawaited_futures # https://github.com/flutter/flutter/issues/5793 + - unnecessary_brace_in_string_interps + - unnecessary_getters_setters + # - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498 + - unnecessary_null_aware_assignments + - unnecessary_null_in_if_null_operators + - unnecessary_overrides + - unnecessary_parenthesis + # - unnecessary_statements # not yet tested + - unnecessary_this + - unrelated_type_equality_checks + - use_rethrow_when_possible + # - use_setters_to_change_properties # not yet tested + # - use_string_buffers # https://github.com/dart-lang/linter/pull/664 + # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review + - valid_regexps \ No newline at end of file diff --git a/third_party/packages/path_parsing/lib/path_parsing.dart b/third_party/packages/path_parsing/lib/path_parsing.dart new file mode 100644 index 00000000000..dd0ef045b24 --- /dev/null +++ b/third_party/packages/path_parsing/lib/path_parsing.dart @@ -0,0 +1 @@ +export 'src/path_parsing.dart'; diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart new file mode 100644 index 00000000000..b8eff9a899c --- /dev/null +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -0,0 +1,743 @@ +// This code has been "translated" largely from the Chromium/blink source +// for SVG path parsing. +// The following files can be cross referenced to the classes and methods here: +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_parser_utilities.cc +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_parser_utilities.h +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_string_source.cc +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_string_source.h +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser.cc +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser.h +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/html/parser/html_parser_idioms.h (IsHTMLSpace) +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser_test.cc + +import 'dart:math' as math show sqrt, max, pi, tan, sin, cos, pow, atan2; + +import 'package:meta/meta.dart'; +import 'package:vector_math/vector_math.dart' show Matrix4; + +import './path_segment_type.dart'; + +/// Parse `svg`, emitting the segment data to `path`. +void writeSvgPathDataToPath(String svg, PathProxy path) { + if (svg == null || svg == '') { + return; + } + + final SvgPathStringSource parser = new SvgPathStringSource(svg); + final SvgPathNormalizer normalizer = new SvgPathNormalizer(); + for (PathSegmentData seg in parser.parseSegments()) { + normalizer.emitSegment(seg, path); + } +} + +/// A receiver for normalized [PathSegmentData]. +abstract class PathProxy { + void moveTo(double x, double y); + void lineTo(double x, double y); + void cubicTo( + double x1, + double y1, + double x2, + double y2, + double x3, + double y3, + ); + void close(); +} + +/// Provides a minimal implementation of a [Point] or [Offset]. +// Takes care of a few things Point doesn't, without requiring Flutter as dependency +@immutable +class _PathOffset { + const _PathOffset(this.dx, this.dy); + + static _PathOffset get zero => const _PathOffset(0.0, 0.0); + final double dx; + final double dy; + + double get direction => math.atan2(dy, dx); + + _PathOffset translate(double translateX, double translateY) => + new _PathOffset(dx + translateX, dy + translateY); + + _PathOffset operator +(_PathOffset other) => + new _PathOffset(dx + other.dx, dy + other.dy); + _PathOffset operator -(_PathOffset other) => + new _PathOffset(dx - other.dx, dy - other.dy); + + _PathOffset operator *(double operand) => + new _PathOffset(dx * operand, dy * operand); +} + +const double _twoPiFloat = math.pi * 2.0; +const double _piOverTwoFloat = math.pi / 2.0; + +class SvgPathStringSource { + SvgPathSegType _previousCommand; + List _codePoints; + int _idx; + + SvgPathStringSource(String string) : assert(string != null) { + _previousCommand = SvgPathSegType.unknown; + _codePoints = string.codeUnits; + _idx = 0; + _skipOptionalSvgSpaces(); + } + + bool _isHtmlSpace(int character) { + // Histogram from Apple's page load test combined with some ad hoc browsing + // some other test suites. + // + // 82%: 216330 non-space characters, all > U+0020 + // 11%: 30017 plain space characters, U+0020 + // 5%: 12099 newline characters, U+000A + // 2%: 5346 tab characters, U+0009 + // + // No other characters seen. No U+000C or U+000D, and no other control + // characters. Accordingly, we check for non-spaces first, then space, then + // newline, then tab, then the other characters. + + return character <= AsciiConstants.space && + (character == AsciiConstants.space || + character == AsciiConstants.slashN || + character == AsciiConstants.slashT || + character == AsciiConstants.slashR || + character == AsciiConstants.slashF); + } + + bool _skipOptionalSvgSpaces() { + while (_idx < _codePoints.length && _isHtmlSpace(_codePoints[_idx])) { + _idx++; + } + return _idx < _codePoints.length; + } + + bool _skipOptionalSvgSpacesOrDelimiter( + [int delimiter = AsciiConstants.comma]) { + if (_idx < _codePoints.length && + !_isHtmlSpace(_codePoints[_idx]) && + _codePoints[_idx] != delimiter) { + return false; + } + if (_skipOptionalSvgSpaces()) { + if (_idx < _codePoints.length && _codePoints[_idx] == delimiter) { + _idx++; + _skipOptionalSvgSpaces(); + } + } + return _idx < _codePoints.length; + } + + bool _isNumberStart(int lookahead) { + return (lookahead >= AsciiConstants.number0 && + lookahead <= AsciiConstants.number9) || + lookahead == AsciiConstants.plus || + lookahead == AsciiConstants.minus || + lookahead == AsciiConstants.period; + } + + SvgPathSegType _maybeImplicitCommand( + int lookahead, SvgPathSegType nextCommand) { + // Check if the current lookahead may start a number - in which case it + // could be the start of an implicit command. The 'close' command does not + // have any parameters though and hence can't have an implicit + // 'continuation'. + if (!_isNumberStart(lookahead) || _previousCommand == SvgPathSegType.close) + return nextCommand; + // Implicit continuations of moveto command translate to linetos. + if (_previousCommand == SvgPathSegType.moveToAbs) { + return SvgPathSegType.lineToAbs; + } + if (_previousCommand == SvgPathSegType.moveToRel) { + return SvgPathSegType.lineToRel; + } + return _previousCommand; + } + + bool _isValidRange(double x) { + return x >= -double.maxFinite && x <= double.maxFinite; + } + + bool _isValidExponent(double x) { + return x >= -37 && x <= 38; + } + + // We use this generic parseNumber function to allow the Path parsing code to + // work at a higher precision internally, without any unnecessary runtime cost + // or code complexity. + double _parseNumber() { + _skipOptionalSvgSpaces(); + + // read the sign + int sign = 1; + final int end = _codePoints.length; + if (_idx < end && _codePoints[_idx] == AsciiConstants.plus) + _idx++; + else if (_idx < end && _codePoints[_idx] == AsciiConstants.minus) { + _idx++; + sign = -1; + } + + if (_idx == end || + ((_codePoints[_idx] < AsciiConstants.number0 || + _codePoints[_idx] > AsciiConstants.number9) && + _codePoints[_idx] != AsciiConstants.period)) + // The first character of a number must be one of [0-9+-.] + throw new StateError( + 'First character of a number must be one of [0-9+-.]'); + + // read the integer part, build right-to-left + final int digitsStart = _idx; + while (_idx < end && + _codePoints[_idx] >= AsciiConstants.number0 && + _codePoints[_idx] <= AsciiConstants.number9) + ++_idx; // Advance to first non-digit. + + double integer = 0.0; + if (_idx != digitsStart) { + int ptrScanIntPart = _idx - 1; + int multiplier = 1; + while (ptrScanIntPart >= digitsStart) { + integer += multiplier * + (_codePoints[ptrScanIntPart--] - AsciiConstants.number0); + + multiplier *= 10; + } + // Bail out early if this overflows. + if (!_isValidRange(integer)) { + throw new StateError('Numeric overflow'); + } + } + + double decimal = 0.0; + if (_idx < end && _codePoints[_idx] == AsciiConstants.period) { + // read the decimals + _idx++; + + // There must be a least one digit following the . + if (_idx >= end || + _codePoints[_idx] < AsciiConstants.number0 || + _codePoints[_idx] > AsciiConstants.number9) + throw new StateError( + 'There must be at least one digit following the .'); + + double frac = 1.0; + while (_idx < end && + _codePoints[_idx] >= AsciiConstants.number0 && + _codePoints[_idx] <= AsciiConstants.number9) { + frac *= 0.1; + decimal += (_codePoints[_idx++] - AsciiConstants.number0) * frac; + } + } + + // When we get here we should have consumed either a digit for the integer + // part or a fractional part (with at least one digit after the '.'.) + assert(digitsStart != _idx); + + double number = integer + decimal; + number *= sign; + + // read the exponent part + if (_idx + 1 < end && + (_codePoints[_idx] == AsciiConstants.lowerE || + _codePoints[_idx] == AsciiConstants.upperE) && + (_codePoints[_idx + 1] != AsciiConstants.lowerX && + _codePoints[_idx + 1] != AsciiConstants.lowerM)) { + _idx++; + + // read the sign of the exponent + bool exponentIsNegative = false; + if (_codePoints[_idx] == AsciiConstants.plus) + _idx++; + else if (_codePoints[_idx] == AsciiConstants.minus) { + _idx++; + exponentIsNegative = true; + } + + // There must be an exponent + if (_idx >= end || + _codePoints[_idx] < AsciiConstants.number0 || + _codePoints[_idx] > AsciiConstants.number9) + throw new StateError('Missing exponent'); + + double exponent = 0.0; + while (_idx < end && + _codePoints[_idx] >= AsciiConstants.number0 && + _codePoints[_idx] <= AsciiConstants.number9) { + exponent *= 10.0; + exponent += _codePoints[_idx] - AsciiConstants.number0; + _idx++; + } + if (exponentIsNegative) { + exponent = -exponent; + } + // Make sure exponent is valid. + if (!_isValidExponent(exponent)) { + throw new StateError('Invalid exponent $exponent'); + } + if (exponent != 0) { + number *= math.pow(10.0, exponent); + } + } + + // Don't return Infinity() or NaN(). + if (!_isValidRange(number)) { + throw new StateError('Numeric overflow'); + } + + // if (mode & kAllowTrailingWhitespace) + _skipOptionalSvgSpacesOrDelimiter(); + + return number; + } + + bool _parseArcFlag() { + if (!hasMoreData) { + throw new StateError('Expected more data'); + } + final int flagChar = _codePoints[_idx]; + _idx++; + _skipOptionalSvgSpacesOrDelimiter(); + + if (flagChar == AsciiConstants.number0) + return false; + else if (flagChar == AsciiConstants.number1) + return true; + else + throw new StateError('Invalid flag value'); + } + + bool get hasMoreData => _idx < _codePoints.length; + + Iterable parseSegments() sync* { + while (hasMoreData) { + yield parseSegment(); + } + } + + PathSegmentData parseSegment() { + assert(hasMoreData); + final PathSegmentData segment = new PathSegmentData(); + final int lookahead = _codePoints[_idx]; + SvgPathSegType command = AsciiConstants.mapLetterToSegmentType(lookahead); + if (_previousCommand == SvgPathSegType.unknown) { + // First command has to be a moveto. + if (command != SvgPathSegType.moveToRel && + command != SvgPathSegType.moveToAbs) { + throw new StateError('Expected to find moveTo command'); + // SetErrorMark(SVGParseStatus::kExpectedMoveToCommand); + // return segment; + } + // Consume command letter. + _idx++; + } else if (command == SvgPathSegType.unknown) { + // Possibly an implicit command. + assert(_previousCommand != SvgPathSegType.unknown); + command = _maybeImplicitCommand(lookahead, command); + if (command == null || command == SvgPathSegType.unknown) { + throw new StateError('Expected a path command'); + } + } else { + // Valid explicit command. + _idx++; + } + + segment.command = _previousCommand = command; + + switch (segment.command) { + case SvgPathSegType.cubicToRel: + case SvgPathSegType.cubicToAbs: + segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); + continue cubic_smooth; + case SvgPathSegType.smoothCubicToRel: + cubic_smooth: + case SvgPathSegType.smoothCubicToAbs: + segment.point2 = new _PathOffset(_parseNumber(), _parseNumber()); + continue quad_smooth; + case SvgPathSegType.moveToRel: + case SvgPathSegType.moveToAbs: + case SvgPathSegType.lineToRel: + case SvgPathSegType.lineToAbs: + case SvgPathSegType.smoothQuadToRel: + quad_smooth: + case SvgPathSegType.smoothQuadToAbs: + segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + break; + case SvgPathSegType.lineToHorizontalRel: + case SvgPathSegType.lineToHorizontalAbs: + segment.targetPoint = + new _PathOffset(_parseNumber(), segment.targetPoint?.dy ?? 0.0); + break; + case SvgPathSegType.lineToVerticalRel: + case SvgPathSegType.lineToVerticalAbs: + segment.targetPoint = + new _PathOffset(segment.targetPoint?.dx ?? 0.0, _parseNumber()); + break; + case SvgPathSegType.close: + _skipOptionalSvgSpaces(); + break; + case SvgPathSegType.quadToRel: + case SvgPathSegType.quadToAbs: + segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); + segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + + break; + case SvgPathSegType.arcToRel: + case SvgPathSegType.arcToAbs: + segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); + segment.arcAngle = _parseNumber(); + segment.arcLarge = _parseArcFlag(); + segment.arcSweep = _parseArcFlag(); + segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + break; + case SvgPathSegType.unknown: + throw new StateError('Unknown segment command'); + } + + return segment; + } +} + +class OffsetHelper { + static _PathOffset reflectedPoint( + _PathOffset reflectedIn, _PathOffset pointToReflect) { + return new _PathOffset(2 * reflectedIn.dx - pointToReflect.dx, + 2 * reflectedIn.dy - pointToReflect.dy); + } + + static const double _kOneOverThree = 1.0 / 3.0; + + /// Blend the points with a ratio (1/3):(2/3). + static _PathOffset blendPoints(_PathOffset p1, _PathOffset p2) { + return new _PathOffset((p1.dx + 2 * p2.dx) * _kOneOverThree, + (p1.dy + 2 * p2.dy) * _kOneOverThree); + } +} + +bool isCubicCommand(SvgPathSegType command) { + return command == SvgPathSegType.cubicToAbs || + command == SvgPathSegType.cubicToRel || + command == SvgPathSegType.smoothCubicToAbs || + command == SvgPathSegType.smoothCubicToRel; +} + +bool isQuadraticCommand(SvgPathSegType command) { + return command == SvgPathSegType.quadToAbs || + command == SvgPathSegType.quadToRel || + command == SvgPathSegType.smoothQuadToAbs || + command == SvgPathSegType.smoothQuadToRel; +} + +// TODO(dnfield): This can probably be cleaned up a bit. Some of this was designed in such a way to pack data/optimize for C++ +// There are probably better/clearer ways to do it for Dart. +class PathSegmentData { + PathSegmentData() + : command = SvgPathSegType.unknown, + arcSweep = false, + arcLarge = false; + + _PathOffset get arcRadii => point1; + + double get arcAngle => point2.dx; + set arcAngle(double angle) => + point2 = new _PathOffset(angle, point2?.dy ?? 0.0); + + double get r1 => arcRadii.dx; + double get r2 => arcRadii.dy; + + bool get largeArcFlag => arcLarge; + bool get sweepFlag => arcSweep; + + double get x => targetPoint.dx; + double get y => targetPoint.dy; + + double get x1 => point1.dx; + double get y1 => point1.dy; + + double get x2 => point2.dx; + double get y2 => point2.dy; + + SvgPathSegType command; + _PathOffset targetPoint; + _PathOffset point1; + _PathOffset point2; + bool arcSweep; + bool arcLarge; + + @override + String toString() { + return 'PathSegmentData{$command $targetPoint $point1 $point2 $arcSweep $arcLarge}'; + } +} + +class SvgPathNormalizer { + _PathOffset _currentPoint = _PathOffset.zero; + _PathOffset _subPathPoint = _PathOffset.zero; + _PathOffset _controlPoint = _PathOffset.zero; + SvgPathSegType _lastCommand = SvgPathSegType.unknown; + + void emitSegment(PathSegmentData segment, PathProxy path) { + final PathSegmentData normSeg = segment; + assert( + normSeg.command == SvgPathSegType.close || normSeg.targetPoint != null); + assert(_currentPoint != null); + // Convert relative points to absolute points. + switch (segment.command) { + case SvgPathSegType.quadToRel: + normSeg.point1 += _currentPoint; + normSeg.targetPoint += _currentPoint; + break; + case SvgPathSegType.cubicToRel: + normSeg.point1 += _currentPoint; + continue smooth_rel; + smooth_rel: + case SvgPathSegType.smoothCubicToRel: + normSeg.point2 += _currentPoint; + continue arc_rel; + case SvgPathSegType.moveToRel: + case SvgPathSegType.lineToRel: + case SvgPathSegType.lineToHorizontalRel: + case SvgPathSegType.lineToVerticalRel: + case SvgPathSegType.smoothQuadToRel: + arc_rel: + case SvgPathSegType.arcToRel: + normSeg.targetPoint += _currentPoint; + break; + case SvgPathSegType.lineToHorizontalAbs: + normSeg.targetPoint = + new _PathOffset(normSeg.targetPoint.dx, _currentPoint.dy); + break; + case SvgPathSegType.lineToVerticalAbs: + normSeg.targetPoint = + new _PathOffset(_currentPoint.dx, normSeg.targetPoint.dy); + break; + case SvgPathSegType.close: + // Reset m_currentPoint for the next path. + normSeg.targetPoint = _subPathPoint; + break; + default: + break; + } + + // Update command verb, handle smooth segments and convert quadratic curve + // segments to cubics. + switch (segment.command) { + case SvgPathSegType.moveToRel: + case SvgPathSegType.moveToAbs: + _subPathPoint = normSeg.targetPoint; + normSeg.command = SvgPathSegType.moveToAbs; + path.moveTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); + break; + case SvgPathSegType.lineToRel: + case SvgPathSegType.lineToAbs: + case SvgPathSegType.lineToHorizontalRel: + case SvgPathSegType.lineToHorizontalAbs: + case SvgPathSegType.lineToVerticalRel: + case SvgPathSegType.lineToVerticalAbs: + normSeg.command = SvgPathSegType.lineToAbs; + path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); + break; + case SvgPathSegType.close: + normSeg.command = SvgPathSegType.close; + path.close(); + break; + case SvgPathSegType.smoothCubicToRel: + case SvgPathSegType.smoothCubicToAbs: + if (!isCubicCommand(_lastCommand)) + normSeg.point1 = _currentPoint; + else + normSeg.point1 = + OffsetHelper.reflectedPoint(_currentPoint, _controlPoint); + continue cubic_abs2; + case SvgPathSegType.cubicToRel: + cubic_abs2: + case SvgPathSegType.cubicToAbs: + _controlPoint = normSeg.point2; + normSeg.command = SvgPathSegType.cubicToAbs; + path.cubicTo(normSeg.point1.dx, normSeg.point1.dy, normSeg.point2.dx, + normSeg.point2.dy, normSeg.targetPoint.dx, normSeg.targetPoint.dy); + break; + case SvgPathSegType.smoothQuadToRel: + case SvgPathSegType.smoothQuadToAbs: + if (!isQuadraticCommand(_lastCommand)) + normSeg.point1 = _currentPoint; + else + normSeg.point1 = + OffsetHelper.reflectedPoint(_currentPoint, _controlPoint); + continue quad_abs2; + case SvgPathSegType.quadToRel: + quad_abs2: + case SvgPathSegType.quadToAbs: + // Save the unmodified control point. + _controlPoint = normSeg.point1; + normSeg.point1 = OffsetHelper.blendPoints(_currentPoint, _controlPoint); + normSeg.point2 = + OffsetHelper.blendPoints(normSeg.targetPoint, _controlPoint); + normSeg.command = SvgPathSegType.cubicToAbs; + path.cubicTo(normSeg.point1.dx, normSeg.point1.dy, normSeg.point2.dx, + normSeg.point2.dy, normSeg.targetPoint.dx, normSeg.targetPoint.dy); + break; + case SvgPathSegType.arcToRel: + case SvgPathSegType.arcToAbs: + if (!_decomposeArcToCubic(_currentPoint, normSeg, path)) { + // On failure, emit a line segment to the target point. + normSeg.command = SvgPathSegType.lineToAbs; + path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); + } else { + // decomposeArcToCubic() has already emitted the normalized + // segments, so set command to PathSegArcAbs, to skip any further + // emit. + normSeg.command = SvgPathSegType.arcToAbs; + } + break; + default: + throw new StateError('Invalid command type in path'); + } + + _currentPoint = normSeg.targetPoint; + + if (!isCubicCommand(segment.command) && + !isQuadraticCommand(segment.command)) { + _controlPoint = _currentPoint; + } + + _lastCommand = segment.command; + } + +// This works by converting the SVG arc to "simple" beziers. +// Partly adapted from Niko's code in kdelibs/kdecore/svgicons. +// See also SVG implementation notes: +// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter + bool _decomposeArcToCubic( + _PathOffset currentPoint, PathSegmentData arcSegment, PathProxy path) { + // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a + // "lineto") joining the endpoints. + // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters + double rx = arcSegment.arcRadii.dx.abs(); + double ry = arcSegment.arcRadii.dy.abs(); + if (rx == 0 || ry == 0) { + return false; + } + + // If the current point and target point for the arc are identical, it should + // be treated as a zero length path. This ensures continuity in animations. + if (arcSegment.targetPoint == currentPoint) { + return false; + } + + final double angle = arcSegment.arcAngle; + + final _PathOffset midPointDistance = + (currentPoint - arcSegment.targetPoint) * 0.5; + + final Matrix4 pointTransform = new Matrix4.identity(); + pointTransform.rotateZ(-angle); + + final _PathOffset transformedMidPoint = _mapPoint( + pointTransform, + new _PathOffset( + midPointDistance.dx, + midPointDistance.dy, + ), + ); + + final double squareRx = rx * rx; + final double squareRy = ry * ry; + final double squareX = transformedMidPoint.dx * transformedMidPoint.dx; + final double squareY = transformedMidPoint.dy * transformedMidPoint.dy; + + // Check if the radii are big enough to draw the arc, scale radii if not. + // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii + final double radiiScale = squareX / squareRx + squareY / squareRy; + if (radiiScale > 1.0) { + rx *= math.sqrt(radiiScale); + ry *= math.sqrt(radiiScale); + } + pointTransform.setIdentity(); + + pointTransform.scale(1.0 / rx, 1.0 / ry); + pointTransform.rotateZ(-angle); + + _PathOffset point1 = _mapPoint(pointTransform, currentPoint); + _PathOffset point2 = _mapPoint(pointTransform, arcSegment.targetPoint); + _PathOffset delta = point2 - point1; + + final double d = delta.dx * delta.dx + delta.dy * delta.dy; + final double scaleFactorSquared = math.max(1.0 / d - 0.25, 0.0); + double scaleFactor = math.sqrt(scaleFactorSquared); + + if (arcSegment.arcSweep == arcSegment.arcLarge) { + scaleFactor = -scaleFactor; + } + + delta = delta * scaleFactor; + final _PathOffset centerPoint = + ((point1 + point2) * 0.5).translate(-delta.dy, delta.dx); + + final double theta1 = (point1 - centerPoint).direction; + final double theta2 = (point2 - centerPoint).direction; + + double thetaArc = theta2 - theta1; + + if (thetaArc < 0.0 && arcSegment.arcSweep) { + thetaArc += _twoPiFloat; + } else if (thetaArc > 0.0 && !arcSegment.arcSweep) { + thetaArc -= _twoPiFloat; + } + + pointTransform.setIdentity(); + pointTransform.rotateZ(angle); + pointTransform.scale(rx, ry); + + // Some results of atan2 on some platform implementations are not exact + // enough. So that we get more cubic curves than expected here. Adding 0.001f + // reduces the count of segments to the correct count. + final int segments = (thetaArc / (_piOverTwoFloat + 0.001)).abs().ceil(); + for (int i = 0; i < segments; ++i) { + final double startTheta = theta1 + i * thetaArc / segments; + final double endTheta = theta1 + (i + 1) * thetaArc / segments; + + final double t = (8.0 / 6.0) * math.tan(0.25 * (endTheta - startTheta)); + if (!t.isFinite) { + return false; + } + final double sinStartTheta = math.sin(startTheta); + final double cosStartTheta = math.cos(startTheta); + final double sinEndTheta = math.sin(endTheta); + final double cosEndTheta = math.cos(endTheta); + + point1 = new _PathOffset( + cosStartTheta - t * sinStartTheta, + sinStartTheta + t * cosStartTheta, + ).translate(centerPoint.dx, centerPoint.dy); + final _PathOffset targetPoint = new _PathOffset( + cosEndTheta, + sinEndTheta, + ).translate(centerPoint.dx, centerPoint.dy); + point2 = targetPoint.translate(t * sinEndTheta, -t * cosEndTheta); + + final PathSegmentData cubicSegment = new PathSegmentData(); + cubicSegment.command = SvgPathSegType.cubicToAbs; + cubicSegment.point1 = _mapPoint(pointTransform, point1); + cubicSegment.point2 = _mapPoint(pointTransform, point2); + cubicSegment.targetPoint = _mapPoint(pointTransform, targetPoint); + + path.cubicTo(cubicSegment.x1, cubicSegment.y1, cubicSegment.x2, + cubicSegment.y2, cubicSegment.x, cubicSegment.y); + //consumer_->EmitSegment(cubicSegment); + } + return true; + } + + _PathOffset _mapPoint(Matrix4 transform, _PathOffset point) { + // a, b, 0.0, 0.0, c, d, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, e, f, 0.0, 1.0 + return new _PathOffset( + transform.storage[0] * point.dx + + transform.storage[4] * point.dy + + transform.storage[12], + transform.storage[1] * point.dx + + transform.storage[5] * point.dy + + transform.storage[13], + ); + } +} diff --git a/third_party/packages/path_parsing/lib/src/path_segment_type.dart b/third_party/packages/path_parsing/lib/src/path_segment_type.dart new file mode 100644 index 00000000000..b104f5635ec --- /dev/null +++ b/third_party/packages/path_parsing/lib/src/path_segment_type.dart @@ -0,0 +1,233 @@ +/// SvgPathSegType enumerates the various path segment commands. +/// +/// [AsciiConstants] houses the ASCII numeric values of these commands +enum SvgPathSegType { + /// Indicates initial state or error + unknown, + + /// Z or z + close, + + /// M + moveToAbs, + + /// m + moveToRel, + + /// L + lineToAbs, + + /// l + lineToRel, + + /// C + cubicToAbs, + + /// c + cubicToRel, + + /// Q + quadToAbs, + + /// q + quadToRel, + + /// A + arcToAbs, + + /// a + arcToRel, + + /// H + lineToHorizontalAbs, + + /// h + lineToHorizontalRel, + + /// V + lineToVerticalAbs, + + /// v + lineToVerticalRel, + + /// S + smoothCubicToAbs, + + /// s + smoothCubicToRel, + + /// T + smoothQuadToAbs, + + /// t + smoothQuadToRel +} + +/// Character constants used internally. Note that this parser does not +/// properly support non-ascii characters in the path, but it does support +/// unicode encoding. +/// +/// Only contains values that are used by the parser (does not contain the full +/// ASCII set). +class AsciiConstants { + const AsciiConstants._(); + + static SvgPathSegType mapLetterToSegmentType(int lookahead) { + return AsciiConstants.letterToSegmentType[lookahead] ?? + SvgPathSegType.unknown; + } + + /// Map to go from ASCII constant to [SvgPathSegType] + static const Map letterToSegmentType = + const { + upperZ: SvgPathSegType.close, + lowerZ: SvgPathSegType.close, + upperM: SvgPathSegType.moveToAbs, + lowerM: SvgPathSegType.moveToRel, + upperL: SvgPathSegType.lineToAbs, + lowerL: SvgPathSegType.lineToRel, + upperC: SvgPathSegType.cubicToAbs, + lowerC: SvgPathSegType.cubicToRel, + upperQ: SvgPathSegType.quadToAbs, + lowerQ: SvgPathSegType.quadToRel, + upperA: SvgPathSegType.arcToAbs, + lowerA: SvgPathSegType.arcToRel, + upperH: SvgPathSegType.lineToHorizontalAbs, + lowerH: SvgPathSegType.lineToHorizontalRel, + upperV: SvgPathSegType.lineToVerticalAbs, + lowerV: SvgPathSegType.lineToVerticalRel, + upperS: SvgPathSegType.smoothCubicToAbs, + lowerS: SvgPathSegType.smoothCubicToRel, + upperT: SvgPathSegType.smoothQuadToAbs, + lowerT: SvgPathSegType.smoothQuadToRel, + }; + + /// `\t` (horizontal tab). + static const int slashT = 9; + + /// `\n` (newline). + static const int slashN = 10; + + /// `\f` (form feed). + static const int slashF = 12; + + /// `\r` (carriage return). + static const int slashR = 13; + + /// ` ` (space). + static const int space = 32; + + /// `+` (plus). + static const int plus = 43; + + /// `,` (comma). + static const int comma = 44; + + /// `-` (minus). + static const int minus = 45; + + /// `.` (period). + static const int period = 46; + + /// 0 (the number zero). + static const int number0 = 48; + + /// 1 (the number one). + static const int number1 = 49; + + /// 2 (the number two). + static const int number2 = 50; + + /// 3 (the number three). + static const int number3 = 51; + + /// 4 (the number four). + static const int number4 = 52; + + /// 5 (the number five). + static const int number5 = 53; + + /// 6 (the number six). + static const int number6 = 54; + + /// 7 (the number seven). + static const int number7 = 55; + + /// 8 (the number eight). + static const int number8 = 56; + + /// 9 (the number nine). + static const int number9 = 57; + + /// A + static const int upperA = 65; + + /// C + static const int upperC = 67; + + /// E + static const int upperE = 69; + + /// H + static const int upperH = 72; + + /// L + static const int upperL = 76; + + /// M + static const int upperM = 77; + + /// Q + static const int upperQ = 81; + + /// S + static const int upperS = 83; + + /// T + static const int upperT = 84; + + /// V + static const int upperV = 86; + + /// Z + static const int upperZ = 90; + + /// a + static const int lowerA = 97; + + /// c + static const int lowerC = 99; + + /// e + static const int lowerE = 101; + + /// h + static const int lowerH = 104; + + /// l + static const int lowerL = 108; + + /// m + static const int lowerM = 109; + + /// q + static const int lowerQ = 113; + + /// s + static const int lowerS = 115; + + /// t + static const int lowerT = 116; + + /// v + static const int lowerV = 118; + + /// x + static const int lowerX = 120; + + /// z + static const int lowerZ = 122; + + /// `~` (tilde) + static const int tilde = 126; +} diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock new file mode 100644 index 00000000000..0e530c2c8f0 --- /dev/null +++ b/third_party/packages/path_parsing/pubspec.lock @@ -0,0 +1,355 @@ +# Generated by pub +# See https://www.dartlang.org/tools/pub/glossary#lockfile +packages: + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.32.4" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.4" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.4+1" + front_end: + dependency: transitive + description: + name: front_end + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.7" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.3+2" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.3+17" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.1+1" + json_rpc_2: + dependency: transitive + description: + name: json_rpc_2 + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + kernel: + dependency: transitive + description: + name: kernel + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.4" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.3+2" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.3+1" + meta: + dependency: "direct main" + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.6+2" + multi_server_socket: + dependency: transitive + description: + name: multi_server_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.4" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + package_resolver: + dependency: transitive + description: + name: package_resolver + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + path: + dependency: "direct dev" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.2" + plugin: + dependency: transitive + description: + name: plugin + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+3" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.6" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.2" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.3+3" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.8" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.2+3" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.5" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.7" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.8" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.42" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + utf: + dependency: transitive + description: + name: utf + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.0+5" + vector_math: + dependency: "direct main" + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + vm_service_client: + dependency: transitive + description: + name: vm_service_client + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.6" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.7+10" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.9" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.15" +sdks: + dart: ">=2.0.0-dev.62.0 <2.0.0" diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml new file mode 100644 index 00000000000..8e200809e3c --- /dev/null +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -0,0 +1,17 @@ +name: path_parsing +version: 0.1.0 +description: > + A Dart library to help with SVG Path parsing and code generation +author: Dan Field +homepage: https://github.com/dnfield/path_parsing + +dependencies: + vector_math: ">=2.0.6 <3.0.0" + meta: ">=1.1.2 <2.0.0" + +dev_dependencies: + path: ^1.5.1 + test: ">=0.12.34 <1.0.0" + +environment: + sdk: ">=1.19.0 <3.0.0" \ No newline at end of file diff --git a/third_party/packages/path_parsing/test/parse_path_test.dart b/third_party/packages/path_parsing/test/parse_path_test.dart new file mode 100644 index 00000000000..c5951b4a8db --- /dev/null +++ b/third_party/packages/path_parsing/test/parse_path_test.dart @@ -0,0 +1,220 @@ +// Test paths taken from: +// * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser_test.cc + +import 'package:path_parsing/path_parsing.dart'; +import 'package:path_parsing/src/path_segment_type.dart'; +import 'package:test/test.dart'; + +// TODO(dnfield): a bunch of better tests could be written to track that commands are actually called with expected values/order +// For now we just want to know that something gets emitted and no exceptions are thrown (that's all the legacy tests really did anyway). +class TestPathProxy extends PathProxy { + bool called = false; + @override + void close() { + called = true; + } + + @override + void cubicTo( + double x1, double y1, double x2, double y2, double x3, double y3) { + called = true; + } + + @override + void lineTo(double x, double y) { + called = true; + } + + @override + void moveTo(double x, double y) { + called = true; + } +} + +void main() { + void assertValidPath(String input) { + final TestPathProxy proxy = new TestPathProxy(); + // these shouldn't throw or assert + writeSvgPathDataToPath(input, proxy); + expect(proxy.called, true); + } + + void assertInvalidPath(String input) { + expect(() => writeSvgPathDataToPath(input, new TestPathProxy()), + throwsStateError); + } + + test('Valid Paths', () { + assertValidPath('M1,2'); + assertValidPath('m1,2'); + assertValidPath('M100,200 m3,4'); + assertValidPath('M100,200 L3,4'); + assertValidPath('M100,200 l3,4'); + assertValidPath('M100,200 H3'); + assertValidPath('M100,200 h3'); + assertValidPath('M100,200 V3'); + assertValidPath('M100,200 v3'); + assertValidPath('M100,200 Z'); + assertValidPath('M100,200 z'); + assertValidPath('M100,200 C3,4,5,6,7,8'); + assertValidPath('M100,200 c3,4,5,6,7,8'); + assertValidPath('M100,200 S3,4,5,6'); + assertValidPath('M100,200 s3,4,5,6'); + assertValidPath('M100,200 Q3,4,5,6'); + assertValidPath('M100,200 q3,4,5,6'); + assertValidPath('M100,200 T3,4'); + assertValidPath('M100,200 t3,4'); + assertValidPath('M100,200 A3,4,5,0,0,6,7'); + assertValidPath('M100,200 A3,4,5,1,0,6,7'); + assertValidPath('M100,200 A3,4,5,0,1,6,7'); + assertValidPath('M100,200 A3,4,5,1,1,6,7'); + assertValidPath('M100,200 a3,4,5,0,0,6,7'); + assertValidPath('M100,200 a3,4,5,0,1,6,7'); + assertValidPath('M100,200 a3,4,5,1,0,6,7'); + assertValidPath('M100,200 a3,4,5,1,1,6,7'); + assertValidPath('M100,200 a3,4,5,006,7'); + assertValidPath('M100,200 a3,4,5,016,7'); + assertValidPath('M100,200 a3,4,5,106,7'); + assertValidPath('M100,200 a3,4,5,116,7'); + assertValidPath( + '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 +20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); + + assertValidPath( + 'M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z'); + + assertValidPath('M1,2,3,4'); + assertValidPath('m100,200,3,4'); + + assertValidPath('M 100-200'); + assertValidPath('M 0.6.5'); + + assertValidPath(' M1,2'); + assertValidPath(' M1,2'); + assertValidPath('\tM1,2'); + assertValidPath('\nM1,2'); + assertValidPath('\rM1,2'); + assertValidPath('M1,2 '); + assertValidPath('M1,2\t'); + assertValidPath('M1,2\n'); + assertValidPath('M1,2\r'); + // assertValidPath(''); + // assertValidPath(' '); + assertValidPath('M.1 .2 L.3 .4 .5 .6'); + assertValidPath('M1,1h2,3'); + assertValidPath('M1,1H2,3'); + assertValidPath('M1,1v2,3'); + assertValidPath('M1,1V2,3'); + assertValidPath('M1,1c2,3 4,5 6,7 8,9 10,11 12,13'); + assertValidPath('M1,1C2,3 4,5 6,7 8,9 10,11 12,13'); + assertValidPath('M1,1s2,3 4,5 6,7 8,9'); + assertValidPath('M1,1S2,3 4,5 6,7 8,9'); + assertValidPath('M1,1q2,3 4,5 6,7 8,9'); + assertValidPath('M1,1Q2,3 4,5 6,7 8,9'); + assertValidPath('M1,1t2,3 4,5'); + assertValidPath('M1,1T2,3 4,5'); + assertValidPath('M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11'); + assertValidPath('M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11'); + assertValidPath( + 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'); + }); + + test('Malformed Paths', () { + assertInvalidPath('M100,200 a3,4,5,2,1,6,7'); + assertInvalidPath('M100,200 a3,4,5,1,2,6,7'); + + assertInvalidPath('\vM1,2'); + assertInvalidPath('xM1,2'); + assertInvalidPath('M1,2\v'); + assertInvalidPath('M1,2x'); + assertInvalidPath('M1,2 L40,0#90'); + + assertInvalidPath('x'); + assertInvalidPath('L1,2'); + + assertInvalidPath('M'); + assertInvalidPath('M\0'); + + assertInvalidPath('M1,1Z0'); + assertInvalidPath('M1,1z0'); + + assertInvalidPath('M1,1c2,3 4,5 6,7 8'); + assertInvalidPath('M1,1C2,3 4,5 6,7 8'); + assertInvalidPath('M1,1s2,3 4,5 6'); + assertInvalidPath('M1,1S2,3 4,5 6'); + assertInvalidPath('M1,1q2,3 4,5 6'); + assertInvalidPath('M1,1Q2,3 4,5 6'); + assertInvalidPath('M1,1t2,3 4'); + assertInvalidPath('M1,1T2,3 4'); + assertInvalidPath('M1,1a2,3,4,0,0,5,6 7'); + assertInvalidPath('M1,1A2,3,4,0,0,5,6 7'); + }); + + test('Missing commands/numbers/flags', () { + // Missing initial moveto. + assertInvalidPath(' 10 10'); + assertInvalidPath('L 10 10'); + // Invalid command letter. + assertInvalidPath('M 10 10 #'); + assertInvalidPath('M 10 10 E 100 100'); + // Invalid number. + assertInvalidPath('M 10 10 L100 '); + assertInvalidPath('M 10 10 L100 #'); + assertInvalidPath('M 10 10 L100#100'); + assertInvalidPath('M0,0 A#,10 0 0,0 20,20'); + assertInvalidPath('M0,0 A10,# 0 0,0 20,20'); + assertInvalidPath('M0,0 A10,10 # 0,0 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,0 #,20'); + assertInvalidPath('M0,0 A10,10 0 0,0 20,#'); + // Invalid arc-flag. + assertInvalidPath('M0,0 A10,10 0 #,0 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,# 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,2 20,20'); + }); + + test('Check character constants', () { + expect(AsciiConstants.slashT, '\t'.codeUnitAt(0)); + expect(AsciiConstants.slashN, '\n'.codeUnitAt(0)); + expect(AsciiConstants.slashF, '\f'.codeUnitAt(0)); + expect(AsciiConstants.slashR, '\r'.codeUnitAt(0)); + expect(AsciiConstants.space, ' '.codeUnitAt(0)); + expect(AsciiConstants.period, '.'.codeUnitAt(0)); + expect(AsciiConstants.plus, '+'.codeUnitAt(0)); + expect(AsciiConstants.comma, ','.codeUnitAt(0)); + expect(AsciiConstants.minus, '-'.codeUnitAt(0)); + expect(AsciiConstants.number0, '0'.codeUnitAt(0)); + expect(AsciiConstants.number1, '1'.codeUnitAt(0)); + expect(AsciiConstants.number2, '2'.codeUnitAt(0)); + expect(AsciiConstants.number3, '3'.codeUnitAt(0)); + expect(AsciiConstants.number4, '4'.codeUnitAt(0)); + expect(AsciiConstants.number5, '5'.codeUnitAt(0)); + expect(AsciiConstants.number6, '6'.codeUnitAt(0)); + expect(AsciiConstants.number7, '7'.codeUnitAt(0)); + expect(AsciiConstants.number8, '8'.codeUnitAt(0)); + expect(AsciiConstants.number9, '9'.codeUnitAt(0)); + expect(AsciiConstants.upperA, 'A'.codeUnitAt(0)); + expect(AsciiConstants.upperC, 'C'.codeUnitAt(0)); + expect(AsciiConstants.upperE, 'E'.codeUnitAt(0)); + expect(AsciiConstants.upperH, 'H'.codeUnitAt(0)); + expect(AsciiConstants.upperL, 'L'.codeUnitAt(0)); + expect(AsciiConstants.upperM, 'M'.codeUnitAt(0)); + expect(AsciiConstants.upperQ, 'Q'.codeUnitAt(0)); + expect(AsciiConstants.upperS, 'S'.codeUnitAt(0)); + expect(AsciiConstants.upperT, 'T'.codeUnitAt(0)); + expect(AsciiConstants.upperV, 'V'.codeUnitAt(0)); + expect(AsciiConstants.upperZ, 'Z'.codeUnitAt(0)); + expect(AsciiConstants.lowerA, 'a'.codeUnitAt(0)); + expect(AsciiConstants.lowerC, 'c'.codeUnitAt(0)); + expect(AsciiConstants.lowerE, 'e'.codeUnitAt(0)); + expect(AsciiConstants.lowerH, 'h'.codeUnitAt(0)); + expect(AsciiConstants.lowerL, 'l'.codeUnitAt(0)); + expect(AsciiConstants.lowerM, 'm'.codeUnitAt(0)); + expect(AsciiConstants.lowerQ, 'q'.codeUnitAt(0)); + expect(AsciiConstants.lowerS, 's'.codeUnitAt(0)); + expect(AsciiConstants.lowerT, 't'.codeUnitAt(0)); + expect(AsciiConstants.lowerV, 'v'.codeUnitAt(0)); + expect(AsciiConstants.lowerX, 'x'.codeUnitAt(0)); + expect(AsciiConstants.lowerZ, 'z'.codeUnitAt(0)); + expect(AsciiConstants.tilde, '~'.codeUnitAt(0)); + }); +} From a5ff723c49c208f0adf84d6645f665ac937409dc Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 30 Jul 2018 11:22:42 -0400 Subject: [PATCH 02/28] add example, fix link --- .../packages/path_parsing/CHANGELOG.md | 1 + .../packages/path_parsing/example/main.dart | 32 +++++++++++++++++++ .../packages/path_parsing/pubspec.yaml | 4 +-- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 third_party/packages/path_parsing/example/main.dart diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index f5e35ab237d..37712a9da11 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,3 +1,4 @@ # CHANGELOG +- 0.1.1: Fix link to homepage in pubspec, add example - 0.1.0: Initial release, based on the 0.2.4 release of path_drawing diff --git a/third_party/packages/path_parsing/example/main.dart b/third_party/packages/path_parsing/example/main.dart new file mode 100644 index 00000000000..efc3bd3a97d --- /dev/null +++ b/third_party/packages/path_parsing/example/main.dart @@ -0,0 +1,32 @@ +import 'package:path_parsing/path_parsing.dart'; + +/// A [PathProxy] that dumps Flutter `Path` commands to the console. +class PathPrinter extends PathProxy { + @override + void close() { + print('Path.close();'); + } + + @override + void cubicTo( + double x1, double y1, double x2, double y2, double x3, double y3) { + print('Path.cubicTo($x1, $y1, $x2, $y2, $x3, $y3);'); + } + + @override + void lineTo(double x, double y) { + print('Path.lineTo($x, $y);'); + } + + @override + void moveTo(double x, double y) { + print('Path.moveTo($x, $y);'); + } +} + +void main() { + const String pathData = + 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'; + + writeSvgPathDataToPath(pathData, new PathPrinter()); +} diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 8e200809e3c..66ff4ea350f 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,9 +1,9 @@ name: path_parsing -version: 0.1.0 +version: 0.1.1 description: > A Dart library to help with SVG Path parsing and code generation author: Dan Field -homepage: https://github.com/dnfield/path_parsing +homepage: https://github.com/dnfield/dart_path_parsing dependencies: vector_math: ">=2.0.6 <3.0.0" From 0f00ef2ec5b6923a194a5c8da6e9aa107ea67749 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 1 Aug 2018 22:10:13 -0400 Subject: [PATCH 03/28] fix smooth command parsing --- .../packages/path_parsing/CHANGELOG.md | 14 +++- .../path_parsing/lib/src/path_parsing.dart | 76 ++++++++++++------- .../packages/path_parsing/pubspec.yaml | 2 +- .../test/parse_path_deep_test.dart | 51 +++++++++++++ 4 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 third_party/packages/path_parsing/test/parse_path_deep_test.dart diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 37712a9da11..e594324c7a5 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,4 +1,14 @@ # CHANGELOG -- 0.1.1: Fix link to homepage in pubspec, add example -- 0.1.0: Initial release, based on the 0.2.4 release of path_drawing +## 0.1.2 + +- Fix bug with smooth curve commands +- Add deep testing + +## 0.1.1 + +- Fix link to homepage in pubspec, add example + +## 0.1.0 + +- Initial release, based on the 0.2.4 release of path_drawing diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index b8eff9a899c..96528a02af4 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -67,6 +67,11 @@ class _PathOffset { _PathOffset operator *(double operand) => new _PathOffset(dx * operand, dy * operand); + + @override + String toString() { + return 'PathOffset{$dx,$dy}'; + } } const double _twoPiFloat = math.pi * 2.0; @@ -380,7 +385,6 @@ class SvgPathStringSource { case SvgPathSegType.quadToAbs: segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); - break; case SvgPathSegType.arcToRel: case SvgPathSegType.arcToAbs: @@ -525,7 +529,7 @@ class SvgPathNormalizer { case SvgPathSegType.moveToRel: case SvgPathSegType.moveToAbs: _subPathPoint = normSeg.targetPoint; - normSeg.command = SvgPathSegType.moveToAbs; + // normSeg.command = SvgPathSegType.moveToAbs; path.moveTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); break; case SvgPathSegType.lineToRel: @@ -534,36 +538,48 @@ class SvgPathNormalizer { case SvgPathSegType.lineToHorizontalAbs: case SvgPathSegType.lineToVerticalRel: case SvgPathSegType.lineToVerticalAbs: - normSeg.command = SvgPathSegType.lineToAbs; + // normSeg.command = SvgPathSegType.lineToAbs; path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); break; case SvgPathSegType.close: - normSeg.command = SvgPathSegType.close; + // normSeg.command = SvgPathSegType.close; path.close(); break; case SvgPathSegType.smoothCubicToRel: case SvgPathSegType.smoothCubicToAbs: - if (!isCubicCommand(_lastCommand)) + if (!isCubicCommand(_lastCommand)) { normSeg.point1 = _currentPoint; - else - normSeg.point1 = - OffsetHelper.reflectedPoint(_currentPoint, _controlPoint); + } else { + normSeg.point1 = OffsetHelper.reflectedPoint( + _currentPoint, + _controlPoint, + ); + } continue cubic_abs2; case SvgPathSegType.cubicToRel: cubic_abs2: case SvgPathSegType.cubicToAbs: _controlPoint = normSeg.point2; - normSeg.command = SvgPathSegType.cubicToAbs; - path.cubicTo(normSeg.point1.dx, normSeg.point1.dy, normSeg.point2.dx, - normSeg.point2.dy, normSeg.targetPoint.dx, normSeg.targetPoint.dy); + // normSeg.command = SvgPathSegType.cubicToAbs; + path.cubicTo( + normSeg.point1.dx, + normSeg.point1.dy, + normSeg.point2.dx, + normSeg.point2.dy, + normSeg.targetPoint.dx, + normSeg.targetPoint.dy, + ); break; case SvgPathSegType.smoothQuadToRel: case SvgPathSegType.smoothQuadToAbs: - if (!isQuadraticCommand(_lastCommand)) + if (!isQuadraticCommand(_lastCommand)) { normSeg.point1 = _currentPoint; - else - normSeg.point1 = - OffsetHelper.reflectedPoint(_currentPoint, _controlPoint); + } else { + normSeg.point1 = OffsetHelper.reflectedPoint( + _currentPoint, + _controlPoint, + ); + } continue quad_abs2; case SvgPathSegType.quadToRel: quad_abs2: @@ -571,23 +587,31 @@ class SvgPathNormalizer { // Save the unmodified control point. _controlPoint = normSeg.point1; normSeg.point1 = OffsetHelper.blendPoints(_currentPoint, _controlPoint); - normSeg.point2 = - OffsetHelper.blendPoints(normSeg.targetPoint, _controlPoint); - normSeg.command = SvgPathSegType.cubicToAbs; - path.cubicTo(normSeg.point1.dx, normSeg.point1.dy, normSeg.point2.dx, - normSeg.point2.dy, normSeg.targetPoint.dx, normSeg.targetPoint.dy); + normSeg.point2 = OffsetHelper.blendPoints( + normSeg.targetPoint, + _controlPoint, + ); + // normSeg.command = SvgPathSegType.cubicToAbs; + path.cubicTo( + normSeg.point1.dx, + normSeg.point1.dy, + normSeg.point2.dx, + normSeg.point2.dy, + normSeg.targetPoint.dx, + normSeg.targetPoint.dy, + ); break; case SvgPathSegType.arcToRel: case SvgPathSegType.arcToAbs: if (!_decomposeArcToCubic(_currentPoint, normSeg, path)) { // On failure, emit a line segment to the target point. - normSeg.command = SvgPathSegType.lineToAbs; + // normSeg.command = SvgPathSegType.lineToAbs; path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); - } else { - // decomposeArcToCubic() has already emitted the normalized - // segments, so set command to PathSegArcAbs, to skip any further - // emit. - normSeg.command = SvgPathSegType.arcToAbs; + // } else { + // // decomposeArcToCubic() has already emitted the normalized + // // segments, so set command to PathSegArcAbs, to skip any further + // // emit. + // // normSeg.command = SvgPathSegType.arcToAbs; } break; default: diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 66ff4ea350f..610653fa7ec 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,5 +1,5 @@ name: path_parsing -version: 0.1.1 +version: 0.1.2 description: > A Dart library to help with SVG Path parsing and code generation author: Dan Field diff --git a/third_party/packages/path_parsing/test/parse_path_deep_test.dart b/third_party/packages/path_parsing/test/parse_path_deep_test.dart new file mode 100644 index 00000000000..0a061dfad2c --- /dev/null +++ b/third_party/packages/path_parsing/test/parse_path_deep_test.dart @@ -0,0 +1,51 @@ +import 'package:path_parsing/path_parsing.dart'; +import 'package:test/test.dart'; + + +class DeepTestPathProxy extends PathProxy { + DeepTestPathProxy(this.expectedCommands); + + final List expectedCommands; + final List actualCommands = []; + + @override + void close() { + actualCommands.add('close()'); + } + + @override + void cubicTo( + double x1, double y1, double x2, double y2, double x3, double y3) { + actualCommands.add('cubicTo($x1, $y1, $x2, $y2, $x3, $y3)'); + } + + @override + void lineTo(double x, double y) { + actualCommands.add('lineTo($x, $y)'); + } + + @override + void moveTo(double x, double y) { + actualCommands.add('moveTo($x, $y)'); + } + + void validate() { + expect(expectedCommands, orderedEquals(actualCommands)); + } +} + +void main() { + void assertValidPath(String input, List commands) { + final DeepTestPathProxy proxy = new DeepTestPathProxy(commands); + writeSvgPathDataToPath(input, proxy); + proxy.validate(); + } + + test('Deep path validation', () { + assertValidPath('M20,30 Q40,5 60,30 T100,30', [ + 'moveTo(20.0, 30.0)', + 'cubicTo(33.33333333333333, 13.333333333333332, 46.666666666666664, 13.333333333333332, 60.0, 30.0)', + 'cubicTo(73.33333333333333, 46.666666666666664, 86.66666666666666, 46.666666666666664, 100.0, 30.0)', + ]); + }); +} From a95496f630c1ed67469d70e6e03b839955d71898 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 25 Oct 2018 10:27:25 -0700 Subject: [PATCH 04/28] Fix decomposeCubic logic --- .../packages/path_parsing/CHANGELOG.md | 5 + .../path_parsing/lib/src/path_parsing.dart | 39 ++- .../packages/path_parsing/pubspec.lock | 26 +- .../packages/path_parsing/pubspec.yaml | 6 +- .../test/parse_path_deep_test.dart | 2 +- .../path_parsing/test/parse_path_test.dart | 245 +++++++++--------- 6 files changed, 173 insertions(+), 150 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index e594324c7a5..54519e6e008 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 0.1.3 + +- Fix a bug in decompose cubic curve - avoid trying to call `toInt()` on `double.infinity` +- Bump test dependency. + ## 0.1.2 - Fix bug with smooth curve commands diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 96528a02af4..6846f11bf09 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -49,7 +49,9 @@ abstract class PathProxy { // Takes care of a few things Point doesn't, without requiring Flutter as dependency @immutable class _PathOffset { - const _PathOffset(this.dx, this.dy); + const _PathOffset(this.dx, this.dy) + : assert(dx != null), + assert(dy != null); static _PathOffset get zero => const _PathOffset(0.0, 0.0); final double dx; @@ -72,16 +74,21 @@ class _PathOffset { String toString() { return 'PathOffset{$dx,$dy}'; } + + @override + bool operator ==(Object other) { + return other is _PathOffset && other.dx == other.dy; + } + + // TODO(dnfield): Use a real hashing function - but this should at least be better than the default. + @override + int get hashCode => (((17 * 23) ^ dx.hashCode) * 23) ^ dy.hashCode; } const double _twoPiFloat = math.pi * 2.0; const double _piOverTwoFloat = math.pi / 2.0; class SvgPathStringSource { - SvgPathSegType _previousCommand; - List _codePoints; - int _idx; - SvgPathStringSource(String string) : assert(string != null) { _previousCommand = SvgPathSegType.unknown; _codePoints = string.codeUnits; @@ -89,6 +96,10 @@ class SvgPathStringSource { _skipOptionalSvgSpaces(); } + SvgPathSegType _previousCommand; + List _codePoints; + int _idx; + bool _isHtmlSpace(int character) { // Histogram from Apple's page load test combined with some ad hoc browsing // some other test suites. @@ -607,11 +618,11 @@ class SvgPathNormalizer { // On failure, emit a line segment to the target point. // normSeg.command = SvgPathSegType.lineToAbs; path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); - // } else { - // // decomposeArcToCubic() has already emitted the normalized - // // segments, so set command to PathSegArcAbs, to skip any further - // // emit. - // // normSeg.command = SvgPathSegType.arcToAbs; + // } else { + // // decomposeArcToCubic() has already emitted the normalized + // // segments, so set command to PathSegArcAbs, to skip any further + // // emit. + // // normSeg.command = SvgPathSegType.arcToAbs; } break; default: @@ -633,7 +644,10 @@ class SvgPathNormalizer { // See also SVG implementation notes: // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter bool _decomposeArcToCubic( - _PathOffset currentPoint, PathSegmentData arcSegment, PathProxy path) { + _PathOffset currentPoint, + PathSegmentData arcSegment, + PathProxy path, + ) { // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a // "lineto") joining the endpoints. // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters @@ -689,6 +703,9 @@ class SvgPathNormalizer { final double d = delta.dx * delta.dx + delta.dy * delta.dy; final double scaleFactorSquared = math.max(1.0 / d - 0.25, 0.0); double scaleFactor = math.sqrt(scaleFactorSquared); + if (scaleFactor == double.infinity || scaleFactor == double.negativeInfinity) { + scaleFactor = 0.0; + } if (arcSegment.arcSweep == arcSegment.arcLarge) { scaleFactor = -scaleFactor; diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock index 0e530c2c8f0..2cbffe08729 100644 --- a/third_party/packages/path_parsing/pubspec.lock +++ b/third_party/packages/path_parsing/pubspec.lock @@ -7,14 +7,14 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.32.4" + version: "0.33.1" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "1.5.0" async: dependency: transitive description: @@ -63,14 +63,14 @@ packages: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.14.4+1" + version: "0.14.6" front_end: dependency: transitive description: name: front_end url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.6+1" glob: dependency: transitive description: @@ -84,14 +84,14 @@ packages: name: html url: "https://pub.dartlang.org" source: hosted - version: "0.13.3+2" + version: "0.13.3+3" http: dependency: transitive description: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.11.3+17" + version: "0.12.0" http_multi_server: dependency: transitive description: @@ -133,7 +133,7 @@ packages: name: kernel url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "0.3.6+1" logging: dependency: transitive description: @@ -189,7 +189,7 @@ packages: name: package_resolver url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.6" path: dependency: "direct dev" description: @@ -245,7 +245,7 @@ packages: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.2+3" + version: "0.2.2+4" source_map_stack_trace: dependency: transitive description: @@ -259,7 +259,7 @@ packages: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.7" + version: "0.10.8" source_span: dependency: transitive description: @@ -287,7 +287,7 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" term_glyph: dependency: transitive description: @@ -301,7 +301,7 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "0.12.42" + version: "1.3.4" typed_data: dependency: transitive description: @@ -352,4 +352,4 @@ packages: source: hosted version: "2.1.15" sdks: - dart: ">=2.0.0-dev.62.0 <2.0.0" + dart: ">=2.0.0 <3.0.0" diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 610653fa7ec..94b7ceb390d 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,7 +1,7 @@ name: path_parsing -version: 0.1.2 +version: 0.1.3 description: > - A Dart library to help with SVG Path parsing and code generation + A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. author: Dan Field homepage: https://github.com/dnfield/dart_path_parsing @@ -11,7 +11,7 @@ dependencies: dev_dependencies: path: ^1.5.1 - test: ">=0.12.34 <1.0.0" + test: ^1.3.4 environment: sdk: ">=1.19.0 <3.0.0" \ No newline at end of file diff --git a/third_party/packages/path_parsing/test/parse_path_deep_test.dart b/third_party/packages/path_parsing/test/parse_path_deep_test.dart index 0a061dfad2c..b23cf214c71 100644 --- a/third_party/packages/path_parsing/test/parse_path_deep_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_deep_test.dart @@ -42,7 +42,7 @@ void main() { } test('Deep path validation', () { - assertValidPath('M20,30 Q40,5 60,30 T100,30', [ + assertValidPath('M20,30 Q40,5 60,30 T100,30', [ 'moveTo(20.0, 30.0)', 'cubicTo(33.33333333333333, 13.333333333333332, 46.666666666666664, 13.333333333333332, 60.0, 30.0)', 'cubicTo(73.33333333333333, 46.666666666666664, 86.66666666666666, 46.666666666666664, 100.0, 30.0)', diff --git a/third_party/packages/path_parsing/test/parse_path_test.dart b/third_party/packages/path_parsing/test/parse_path_test.dart index c5951b4a8db..4d684723822 100644 --- a/third_party/packages/path_parsing/test/parse_path_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_test.dart @@ -45,131 +45,132 @@ void main() { } test('Valid Paths', () { - assertValidPath('M1,2'); - assertValidPath('m1,2'); - assertValidPath('M100,200 m3,4'); - assertValidPath('M100,200 L3,4'); - assertValidPath('M100,200 l3,4'); - assertValidPath('M100,200 H3'); - assertValidPath('M100,200 h3'); - assertValidPath('M100,200 V3'); - assertValidPath('M100,200 v3'); - assertValidPath('M100,200 Z'); - assertValidPath('M100,200 z'); - assertValidPath('M100,200 C3,4,5,6,7,8'); - assertValidPath('M100,200 c3,4,5,6,7,8'); - assertValidPath('M100,200 S3,4,5,6'); - assertValidPath('M100,200 s3,4,5,6'); - assertValidPath('M100,200 Q3,4,5,6'); - assertValidPath('M100,200 q3,4,5,6'); - assertValidPath('M100,200 T3,4'); - assertValidPath('M100,200 t3,4'); - assertValidPath('M100,200 A3,4,5,0,0,6,7'); - assertValidPath('M100,200 A3,4,5,1,0,6,7'); - assertValidPath('M100,200 A3,4,5,0,1,6,7'); - assertValidPath('M100,200 A3,4,5,1,1,6,7'); - assertValidPath('M100,200 a3,4,5,0,0,6,7'); - assertValidPath('M100,200 a3,4,5,0,1,6,7'); - assertValidPath('M100,200 a3,4,5,1,0,6,7'); - assertValidPath('M100,200 a3,4,5,1,1,6,7'); - assertValidPath('M100,200 a3,4,5,006,7'); - assertValidPath('M100,200 a3,4,5,016,7'); - assertValidPath('M100,200 a3,4,5,106,7'); - assertValidPath('M100,200 a3,4,5,116,7'); - assertValidPath( - '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 -20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); - - assertValidPath( - 'M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z'); - - assertValidPath('M1,2,3,4'); - assertValidPath('m100,200,3,4'); - - assertValidPath('M 100-200'); - assertValidPath('M 0.6.5'); - - assertValidPath(' M1,2'); - assertValidPath(' M1,2'); - assertValidPath('\tM1,2'); - assertValidPath('\nM1,2'); - assertValidPath('\rM1,2'); - assertValidPath('M1,2 '); - assertValidPath('M1,2\t'); - assertValidPath('M1,2\n'); - assertValidPath('M1,2\r'); - // assertValidPath(''); - // assertValidPath(' '); - assertValidPath('M.1 .2 L.3 .4 .5 .6'); - assertValidPath('M1,1h2,3'); - assertValidPath('M1,1H2,3'); - assertValidPath('M1,1v2,3'); - assertValidPath('M1,1V2,3'); - assertValidPath('M1,1c2,3 4,5 6,7 8,9 10,11 12,13'); - assertValidPath('M1,1C2,3 4,5 6,7 8,9 10,11 12,13'); - assertValidPath('M1,1s2,3 4,5 6,7 8,9'); - assertValidPath('M1,1S2,3 4,5 6,7 8,9'); - assertValidPath('M1,1q2,3 4,5 6,7 8,9'); - assertValidPath('M1,1Q2,3 4,5 6,7 8,9'); - assertValidPath('M1,1t2,3 4,5'); - assertValidPath('M1,1T2,3 4,5'); - assertValidPath('M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11'); - assertValidPath('M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11'); - assertValidPath( - 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'); +// assertValidPath('M1,2'); +// assertValidPath('m1,2'); +// assertValidPath('M100,200 m3,4'); +// assertValidPath('M100,200 L3,4'); +// assertValidPath('M100,200 l3,4'); +// assertValidPath('M100,200 H3'); +// assertValidPath('M100,200 h3'); +// assertValidPath('M100,200 V3'); +// assertValidPath('M100,200 v3'); +// assertValidPath('M100,200 Z'); +// assertValidPath('M100,200 z'); +// assertValidPath('M100,200 C3,4,5,6,7,8'); +// assertValidPath('M100,200 c3,4,5,6,7,8'); +// assertValidPath('M100,200 S3,4,5,6'); +// assertValidPath('M100,200 s3,4,5,6'); +// assertValidPath('M100,200 Q3,4,5,6'); +// assertValidPath('M100,200 q3,4,5,6'); +// assertValidPath('M100,200 T3,4'); +// assertValidPath('M100,200 t3,4'); +// assertValidPath('M100,200 A3,4,5,0,0,6,7'); +// assertValidPath('M100,200 A3,4,5,1,0,6,7'); +// assertValidPath('M100,200 A3,4,5,0,1,6,7'); +// assertValidPath('M100,200 A3,4,5,1,1,6,7'); +// assertValidPath('M100,200 a3,4,5,0,0,6,7'); +// assertValidPath('M100,200 a3,4,5,0,1,6,7'); +// assertValidPath('M100,200 a3,4,5,1,0,6,7'); +// assertValidPath('M100,200 a3,4,5,1,1,6,7'); +// assertValidPath('M100,200 a3,4,5,006,7'); +// assertValidPath('M100,200 a3,4,5,016,7'); +// assertValidPath('M100,200 a3,4,5,106,7'); +// assertValidPath('M100,200 a3,4,5,116,7'); +// assertValidPath( +// '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 +// 20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); + +// assertValidPath( +// 'M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z'); + +// assertValidPath('M1,2,3,4'); +// assertValidPath('m100,200,3,4'); + +// assertValidPath('M 100-200'); +// assertValidPath('M 0.6.5'); + +// assertValidPath(' M1,2'); +// assertValidPath(' M1,2'); +// assertValidPath('\tM1,2'); +// assertValidPath('\nM1,2'); +// assertValidPath('\rM1,2'); +// assertValidPath('M1,2 '); +// assertValidPath('M1,2\t'); +// assertValidPath('M1,2\n'); +// assertValidPath('M1,2\r'); +// // assertValidPath(''); +// // assertValidPath(' '); +// assertValidPath('M.1 .2 L.3 .4 .5 .6'); +// assertValidPath('M1,1h2,3'); +// assertValidPath('M1,1H2,3'); +// assertValidPath('M1,1v2,3'); +// assertValidPath('M1,1V2,3'); +// assertValidPath('M1,1c2,3 4,5 6,7 8,9 10,11 12,13'); +// assertValidPath('M1,1C2,3 4,5 6,7 8,9 10,11 12,13'); +// assertValidPath('M1,1s2,3 4,5 6,7 8,9'); +// assertValidPath('M1,1S2,3 4,5 6,7 8,9'); +// assertValidPath('M1,1q2,3 4,5 6,7 8,9'); +// assertValidPath('M1,1Q2,3 4,5 6,7 8,9'); +// assertValidPath('M1,1t2,3 4,5'); +// assertValidPath('M1,1T2,3 4,5'); +// assertValidPath('M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11'); +// assertValidPath('M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11'); +// assertValidPath( +// 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'); + assertValidPath('m18 11.8a.41.41 0 0 1 .24.08l.59.43h.05.72a.4.4 0 0 1 .39.28l.22.69a.08.08 0 0 0 0 0l.58.43a.41.41 0 0 1 .15.45l-.22.68a.09.09 0 0 0 0 .07l.22.68a.4.4 0 0 1 -.15.46l-.58.42a.1.1 0 0 0 0 0l-.22.68a.41.41 0 0 1 -.38.29h-.79l-.58.43a.41.41 0 0 1 -.24.08.46.46 0 0 1 -.24-.08l-.58-.43h-.06-.72a.41.41 0 0 1 -.39-.28l-.22-.68a.1.1 0 0 0 0 0l-.58-.43a.42.42 0 0 1 -.15-.46l.23-.67v-.02l-.29-.68a.43.43 0 0 1 .15-.46l.58-.42a.1.1 0 0 0 0-.05l.27-.69a.42.42 0 0 1 .39-.28h.78l.58-.43a.43.43 0 0 1 .25-.09m0-1a1.37 1.37 0 0 0 -.83.27l-.34.25h-.43a1.42 1.42 0 0 0 -1.34 1l-.13.4-.35.25a1.42 1.42 0 0 0 -.51 1.58l.13.4-.13.4a1.39 1.39 0 0 0 .52 1.59l.34.25.13.4a1.41 1.41 0 0 0 1.34 1h.43l.34.26a1.44 1.44 0 0 0 .83.27 1.38 1.38 0 0 0 .83-.28l.35-.24h.43a1.4 1.4 0 0 0 1.33-1l.13-.4.35-.26a1.39 1.39 0 0 0 .51-1.57l-.13-.4.13-.41a1.4 1.4 0 0 0 -.51-1.56l-.35-.25-.13-.41a1.4 1.4 0 0 0 -1.34-1h-.42l-.34-.26a1.43 1.43 0 0 0 -.84-.28z'); }); test('Malformed Paths', () { - assertInvalidPath('M100,200 a3,4,5,2,1,6,7'); - assertInvalidPath('M100,200 a3,4,5,1,2,6,7'); - - assertInvalidPath('\vM1,2'); - assertInvalidPath('xM1,2'); - assertInvalidPath('M1,2\v'); - assertInvalidPath('M1,2x'); - assertInvalidPath('M1,2 L40,0#90'); - - assertInvalidPath('x'); - assertInvalidPath('L1,2'); - - assertInvalidPath('M'); - assertInvalidPath('M\0'); - - assertInvalidPath('M1,1Z0'); - assertInvalidPath('M1,1z0'); - - assertInvalidPath('M1,1c2,3 4,5 6,7 8'); - assertInvalidPath('M1,1C2,3 4,5 6,7 8'); - assertInvalidPath('M1,1s2,3 4,5 6'); - assertInvalidPath('M1,1S2,3 4,5 6'); - assertInvalidPath('M1,1q2,3 4,5 6'); - assertInvalidPath('M1,1Q2,3 4,5 6'); - assertInvalidPath('M1,1t2,3 4'); - assertInvalidPath('M1,1T2,3 4'); - assertInvalidPath('M1,1a2,3,4,0,0,5,6 7'); - assertInvalidPath('M1,1A2,3,4,0,0,5,6 7'); - }); - - test('Missing commands/numbers/flags', () { - // Missing initial moveto. - assertInvalidPath(' 10 10'); - assertInvalidPath('L 10 10'); - // Invalid command letter. - assertInvalidPath('M 10 10 #'); - assertInvalidPath('M 10 10 E 100 100'); - // Invalid number. - assertInvalidPath('M 10 10 L100 '); - assertInvalidPath('M 10 10 L100 #'); - assertInvalidPath('M 10 10 L100#100'); - assertInvalidPath('M0,0 A#,10 0 0,0 20,20'); - assertInvalidPath('M0,0 A10,# 0 0,0 20,20'); - assertInvalidPath('M0,0 A10,10 # 0,0 20,20'); - assertInvalidPath('M0,0 A10,10 0 0,0 #,20'); - assertInvalidPath('M0,0 A10,10 0 0,0 20,#'); - // Invalid arc-flag. - assertInvalidPath('M0,0 A10,10 0 #,0 20,20'); - assertInvalidPath('M0,0 A10,10 0 0,# 20,20'); - assertInvalidPath('M0,0 A10,10 0 0,2 20,20'); + // assertInvalidPath('M100,200 a3,4,5,2,1,6,7'); + // assertInvalidPath('M100,200 a3,4,5,1,2,6,7'); + + // assertInvalidPath('\vM1,2'); + // assertInvalidPath('xM1,2'); + // assertInvalidPath('M1,2\v'); + // assertInvalidPath('M1,2x'); + // assertInvalidPath('M1,2 L40,0#90'); + + // assertInvalidPath('x'); + // assertInvalidPath('L1,2'); + + // assertInvalidPath('M'); + // assertInvalidPath('M\0'); + + // assertInvalidPath('M1,1Z0'); + // assertInvalidPath('M1,1z0'); + + // assertInvalidPath('M1,1c2,3 4,5 6,7 8'); + // assertInvalidPath('M1,1C2,3 4,5 6,7 8'); + // assertInvalidPath('M1,1s2,3 4,5 6'); + // assertInvalidPath('M1,1S2,3 4,5 6'); + // assertInvalidPath('M1,1q2,3 4,5 6'); + // assertInvalidPath('M1,1Q2,3 4,5 6'); + // assertInvalidPath('M1,1t2,3 4'); + // assertInvalidPath('M1,1T2,3 4'); + // assertInvalidPath('M1,1a2,3,4,0,0,5,6 7'); + // assertInvalidPath('M1,1A2,3,4,0,0,5,6 7'); + // }); + + // test('Missing commands/numbers/flags', () { + // // Missing initial moveto. + // assertInvalidPath(' 10 10'); + // assertInvalidPath('L 10 10'); + // // Invalid command letter. + // assertInvalidPath('M 10 10 #'); + // assertInvalidPath('M 10 10 E 100 100'); + // // Invalid number. + // assertInvalidPath('M 10 10 L100 '); + // assertInvalidPath('M 10 10 L100 #'); + // assertInvalidPath('M 10 10 L100#100'); + // assertInvalidPath('M0,0 A#,10 0 0,0 20,20'); + // assertInvalidPath('M0,0 A10,# 0 0,0 20,20'); + // assertInvalidPath('M0,0 A10,10 # 0,0 20,20'); + // assertInvalidPath('M0,0 A10,10 0 0,0 #,20'); + // assertInvalidPath('M0,0 A10,10 0 0,0 20,#'); + // // Invalid arc-flag. + // assertInvalidPath('M0,0 A10,10 0 #,0 20,20'); + // assertInvalidPath('M0,0 A10,10 0 0,# 20,20'); + // assertInvalidPath('M0,0 A10,10 0 0,2 20,20'); }); test('Check character constants', () { From 11687b409d77bc3908b239e2014f4d67e4d9ed20 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 25 Oct 2018 10:43:35 -0700 Subject: [PATCH 05/28] uncomment/format tests --- .../path_parsing/test/parse_path_test.dart | 267 ++++++++++-------- 1 file changed, 144 insertions(+), 123 deletions(-) diff --git a/third_party/packages/path_parsing/test/parse_path_test.dart b/third_party/packages/path_parsing/test/parse_path_test.dart index 4d684723822..631ff4aab17 100644 --- a/third_party/packages/path_parsing/test/parse_path_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_test.dart @@ -45,132 +45,153 @@ void main() { } test('Valid Paths', () { -// assertValidPath('M1,2'); -// assertValidPath('m1,2'); -// assertValidPath('M100,200 m3,4'); -// assertValidPath('M100,200 L3,4'); -// assertValidPath('M100,200 l3,4'); -// assertValidPath('M100,200 H3'); -// assertValidPath('M100,200 h3'); -// assertValidPath('M100,200 V3'); -// assertValidPath('M100,200 v3'); -// assertValidPath('M100,200 Z'); -// assertValidPath('M100,200 z'); -// assertValidPath('M100,200 C3,4,5,6,7,8'); -// assertValidPath('M100,200 c3,4,5,6,7,8'); -// assertValidPath('M100,200 S3,4,5,6'); -// assertValidPath('M100,200 s3,4,5,6'); -// assertValidPath('M100,200 Q3,4,5,6'); -// assertValidPath('M100,200 q3,4,5,6'); -// assertValidPath('M100,200 T3,4'); -// assertValidPath('M100,200 t3,4'); -// assertValidPath('M100,200 A3,4,5,0,0,6,7'); -// assertValidPath('M100,200 A3,4,5,1,0,6,7'); -// assertValidPath('M100,200 A3,4,5,0,1,6,7'); -// assertValidPath('M100,200 A3,4,5,1,1,6,7'); -// assertValidPath('M100,200 a3,4,5,0,0,6,7'); -// assertValidPath('M100,200 a3,4,5,0,1,6,7'); -// assertValidPath('M100,200 a3,4,5,1,0,6,7'); -// assertValidPath('M100,200 a3,4,5,1,1,6,7'); -// assertValidPath('M100,200 a3,4,5,006,7'); -// assertValidPath('M100,200 a3,4,5,016,7'); -// assertValidPath('M100,200 a3,4,5,106,7'); -// assertValidPath('M100,200 a3,4,5,116,7'); -// assertValidPath( -// '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 -// 20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); - -// assertValidPath( -// 'M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z'); - -// assertValidPath('M1,2,3,4'); -// assertValidPath('m100,200,3,4'); - -// assertValidPath('M 100-200'); -// assertValidPath('M 0.6.5'); - -// assertValidPath(' M1,2'); -// assertValidPath(' M1,2'); -// assertValidPath('\tM1,2'); -// assertValidPath('\nM1,2'); -// assertValidPath('\rM1,2'); -// assertValidPath('M1,2 '); -// assertValidPath('M1,2\t'); -// assertValidPath('M1,2\n'); -// assertValidPath('M1,2\r'); -// // assertValidPath(''); -// // assertValidPath(' '); -// assertValidPath('M.1 .2 L.3 .4 .5 .6'); -// assertValidPath('M1,1h2,3'); -// assertValidPath('M1,1H2,3'); -// assertValidPath('M1,1v2,3'); -// assertValidPath('M1,1V2,3'); -// assertValidPath('M1,1c2,3 4,5 6,7 8,9 10,11 12,13'); -// assertValidPath('M1,1C2,3 4,5 6,7 8,9 10,11 12,13'); -// assertValidPath('M1,1s2,3 4,5 6,7 8,9'); -// assertValidPath('M1,1S2,3 4,5 6,7 8,9'); -// assertValidPath('M1,1q2,3 4,5 6,7 8,9'); -// assertValidPath('M1,1Q2,3 4,5 6,7 8,9'); -// assertValidPath('M1,1t2,3 4,5'); -// assertValidPath('M1,1T2,3 4,5'); -// assertValidPath('M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11'); -// assertValidPath('M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11'); -// assertValidPath( -// 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'); - assertValidPath('m18 11.8a.41.41 0 0 1 .24.08l.59.43h.05.72a.4.4 0 0 1 .39.28l.22.69a.08.08 0 0 0 0 0l.58.43a.41.41 0 0 1 .15.45l-.22.68a.09.09 0 0 0 0 .07l.22.68a.4.4 0 0 1 -.15.46l-.58.42a.1.1 0 0 0 0 0l-.22.68a.41.41 0 0 1 -.38.29h-.79l-.58.43a.41.41 0 0 1 -.24.08.46.46 0 0 1 -.24-.08l-.58-.43h-.06-.72a.41.41 0 0 1 -.39-.28l-.22-.68a.1.1 0 0 0 0 0l-.58-.43a.42.42 0 0 1 -.15-.46l.23-.67v-.02l-.29-.68a.43.43 0 0 1 .15-.46l.58-.42a.1.1 0 0 0 0-.05l.27-.69a.42.42 0 0 1 .39-.28h.78l.58-.43a.43.43 0 0 1 .25-.09m0-1a1.37 1.37 0 0 0 -.83.27l-.34.25h-.43a1.42 1.42 0 0 0 -1.34 1l-.13.4-.35.25a1.42 1.42 0 0 0 -.51 1.58l.13.4-.13.4a1.39 1.39 0 0 0 .52 1.59l.34.25.13.4a1.41 1.41 0 0 0 1.34 1h.43l.34.26a1.44 1.44 0 0 0 .83.27 1.38 1.38 0 0 0 .83-.28l.35-.24h.43a1.4 1.4 0 0 0 1.33-1l.13-.4.35-.26a1.39 1.39 0 0 0 .51-1.57l-.13-.4.13-.41a1.4 1.4 0 0 0 -.51-1.56l-.35-.25-.13-.41a1.4 1.4 0 0 0 -1.34-1h-.42l-.34-.26a1.43 1.43 0 0 0 -.84-.28z'); + assertValidPath('M1,2'); + assertValidPath('m1,2'); + assertValidPath('M100,200 m3,4'); + assertValidPath('M100,200 L3,4'); + assertValidPath('M100,200 l3,4'); + assertValidPath('M100,200 H3'); + assertValidPath('M100,200 h3'); + assertValidPath('M100,200 V3'); + assertValidPath('M100,200 v3'); + assertValidPath('M100,200 Z'); + assertValidPath('M100,200 z'); + assertValidPath('M100,200 C3,4,5,6,7,8'); + assertValidPath('M100,200 c3,4,5,6,7,8'); + assertValidPath('M100,200 S3,4,5,6'); + assertValidPath('M100,200 s3,4,5,6'); + assertValidPath('M100,200 Q3,4,5,6'); + assertValidPath('M100,200 q3,4,5,6'); + assertValidPath('M100,200 T3,4'); + assertValidPath('M100,200 t3,4'); + assertValidPath('M100,200 A3,4,5,0,0,6,7'); + assertValidPath('M100,200 A3,4,5,1,0,6,7'); + assertValidPath('M100,200 A3,4,5,0,1,6,7'); + assertValidPath('M100,200 A3,4,5,1,1,6,7'); + assertValidPath('M100,200 a3,4,5,0,0,6,7'); + assertValidPath('M100,200 a3,4,5,0,1,6,7'); + assertValidPath('M100,200 a3,4,5,1,0,6,7'); + assertValidPath('M100,200 a3,4,5,1,1,6,7'); + assertValidPath('M100,200 a3,4,5,006,7'); + assertValidPath('M100,200 a3,4,5,016,7'); + assertValidPath('M100,200 a3,4,5,106,7'); + assertValidPath('M100,200 a3,4,5,116,7'); + assertValidPath( + '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 +20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); + + assertValidPath( + 'M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z'); + + assertValidPath('M1,2,3,4'); + assertValidPath('m100,200,3,4'); + + assertValidPath('M 100-200'); + assertValidPath('M 0.6.5'); + + assertValidPath(' M1,2'); + assertValidPath(' M1,2'); + assertValidPath('\tM1,2'); + assertValidPath('\nM1,2'); + assertValidPath('\rM1,2'); + assertValidPath('M1,2 '); + assertValidPath('M1,2\t'); + assertValidPath('M1,2\n'); + assertValidPath('M1,2\r'); + // assertValidPath(''); + // assertValidPath(' '); + assertValidPath('M.1 .2 L.3 .4 .5 .6'); + assertValidPath('M1,1h2,3'); + assertValidPath('M1,1H2,3'); + assertValidPath('M1,1v2,3'); + assertValidPath('M1,1V2,3'); + assertValidPath('M1,1c2,3 4,5 6,7 8,9 10,11 12,13'); + assertValidPath('M1,1C2,3 4,5 6,7 8,9 10,11 12,13'); + assertValidPath('M1,1s2,3 4,5 6,7 8,9'); + assertValidPath('M1,1S2,3 4,5 6,7 8,9'); + assertValidPath('M1,1q2,3 4,5 6,7 8,9'); + assertValidPath('M1,1Q2,3 4,5 6,7 8,9'); + assertValidPath('M1,1t2,3 4,5'); + assertValidPath('M1,1T2,3 4,5'); + assertValidPath('M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11'); + assertValidPath('M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11'); + assertValidPath( + 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 ' + '-4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 ' + '0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803' + 'C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 ' + '4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 ' + '21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 ' + '17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 ' + '-0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976' + 'C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 ' + '17.1277 27.2802 8.87841 22.1595 3.80852Z'); + assertValidPath( + 'm18 11.8a.41.41 0 0 1 .24.08l.59.43h.05.72a.4.4 0 0 1 .39.28l.22.69a.08.08 0 ' + '0 0 0 0l.58.43a.41.41 0 0 1 .15.45l-.22.68a.09.09 0 0 0 0 .07l.22.68a.4.4 0 0 1 ' + '-.15.46l-.58.42a.1.1 0 0 0 0 0l-.22.68a.41.41 0 0 1 -.38.29h-.79l-.58.43a.41.41 0 ' + '0 1 -.24.08.46.46 0 0 1 -.24-.08l-.58-.43h-.06-.72a.41.41 0 0 1 -.39-.28l-.22-.68' + 'a.1.1 0 0 0 0 0l-.58-.43a.42.42 0 0 1 -.15-.46l.23-.67v-.02l-.29-.68a.43.43 0 0 1 ' + '.15-.46l.58-.42a.1.1 0 0 0 0-.05l.27-.69a.42.42 0 0 1 .39-.28h.78l.58-.43a.43.43 0 ' + '0 1 .25-.09m0-1a1.37 1.37 0 0 0 -.83.27l-.34.25h-.43a1.42 1.42 0 0 0 -1.34 1l-.13.4' + '-.35.25a1.42 1.42 0 0 0 -.51 1.58l.13.4-.13.4a1.39 1.39 0 0 0 .52 1.59l.34.25.13.4' + 'a1.41 1.41 0 0 0 1.34 1h.43l.34.26a1.44 1.44 0 0 0 .83.27 1.38 1.38 0 0 0 .83-.28' + 'l.35-.24h.43a1.4 1.4 0 0 0 1.33-1l.13-.4.35-.26a1.39 1.39 0 0 0 .51-1.57l-.13-.4.13-.41' + 'a1.4 1.4 0 0 0 -.51-1.56l-.35-.25-.13-.41a1.4 1.4 0 0 0 -1.34-1h-.42l-.34-.26a1.43 1.43 ' + '0 0 0 -.84-.28z'); }); test('Malformed Paths', () { - // assertInvalidPath('M100,200 a3,4,5,2,1,6,7'); - // assertInvalidPath('M100,200 a3,4,5,1,2,6,7'); - - // assertInvalidPath('\vM1,2'); - // assertInvalidPath('xM1,2'); - // assertInvalidPath('M1,2\v'); - // assertInvalidPath('M1,2x'); - // assertInvalidPath('M1,2 L40,0#90'); - - // assertInvalidPath('x'); - // assertInvalidPath('L1,2'); - - // assertInvalidPath('M'); - // assertInvalidPath('M\0'); - - // assertInvalidPath('M1,1Z0'); - // assertInvalidPath('M1,1z0'); - - // assertInvalidPath('M1,1c2,3 4,5 6,7 8'); - // assertInvalidPath('M1,1C2,3 4,5 6,7 8'); - // assertInvalidPath('M1,1s2,3 4,5 6'); - // assertInvalidPath('M1,1S2,3 4,5 6'); - // assertInvalidPath('M1,1q2,3 4,5 6'); - // assertInvalidPath('M1,1Q2,3 4,5 6'); - // assertInvalidPath('M1,1t2,3 4'); - // assertInvalidPath('M1,1T2,3 4'); - // assertInvalidPath('M1,1a2,3,4,0,0,5,6 7'); - // assertInvalidPath('M1,1A2,3,4,0,0,5,6 7'); - // }); - - // test('Missing commands/numbers/flags', () { - // // Missing initial moveto. - // assertInvalidPath(' 10 10'); - // assertInvalidPath('L 10 10'); - // // Invalid command letter. - // assertInvalidPath('M 10 10 #'); - // assertInvalidPath('M 10 10 E 100 100'); - // // Invalid number. - // assertInvalidPath('M 10 10 L100 '); - // assertInvalidPath('M 10 10 L100 #'); - // assertInvalidPath('M 10 10 L100#100'); - // assertInvalidPath('M0,0 A#,10 0 0,0 20,20'); - // assertInvalidPath('M0,0 A10,# 0 0,0 20,20'); - // assertInvalidPath('M0,0 A10,10 # 0,0 20,20'); - // assertInvalidPath('M0,0 A10,10 0 0,0 #,20'); - // assertInvalidPath('M0,0 A10,10 0 0,0 20,#'); - // // Invalid arc-flag. - // assertInvalidPath('M0,0 A10,10 0 #,0 20,20'); - // assertInvalidPath('M0,0 A10,10 0 0,# 20,20'); - // assertInvalidPath('M0,0 A10,10 0 0,2 20,20'); + assertInvalidPath('M100,200 a3,4,5,2,1,6,7'); + assertInvalidPath('M100,200 a3,4,5,1,2,6,7'); + + assertInvalidPath('\vM1,2'); + assertInvalidPath('xM1,2'); + assertInvalidPath('M1,2\v'); + assertInvalidPath('M1,2x'); + assertInvalidPath('M1,2 L40,0#90'); + + assertInvalidPath('x'); + assertInvalidPath('L1,2'); + + assertInvalidPath('M'); + assertInvalidPath('M\0'); + + assertInvalidPath('M1,1Z0'); + assertInvalidPath('M1,1z0'); + + assertInvalidPath('M1,1c2,3 4,5 6,7 8'); + assertInvalidPath('M1,1C2,3 4,5 6,7 8'); + assertInvalidPath('M1,1s2,3 4,5 6'); + assertInvalidPath('M1,1S2,3 4,5 6'); + assertInvalidPath('M1,1q2,3 4,5 6'); + assertInvalidPath('M1,1Q2,3 4,5 6'); + assertInvalidPath('M1,1t2,3 4'); + assertInvalidPath('M1,1T2,3 4'); + assertInvalidPath('M1,1a2,3,4,0,0,5,6 7'); + assertInvalidPath('M1,1A2,3,4,0,0,5,6 7'); + }); + + test('Missing commands/numbers/flags', () { + // Missing initial moveto. + assertInvalidPath(' 10 10'); + assertInvalidPath('L 10 10'); + // Invalid command letter. + assertInvalidPath('M 10 10 #'); + assertInvalidPath('M 10 10 E 100 100'); + // Invalid number. + assertInvalidPath('M 10 10 L100 '); + assertInvalidPath('M 10 10 L100 #'); + assertInvalidPath('M 10 10 L100#100'); + assertInvalidPath('M0,0 A#,10 0 0,0 20,20'); + assertInvalidPath('M0,0 A10,# 0 0,0 20,20'); + assertInvalidPath('M0,0 A10,10 # 0,0 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,0 #,20'); + assertInvalidPath('M0,0 A10,10 0 0,0 20,#'); + // Invalid arc-flag. + assertInvalidPath('M0,0 A10,10 0 #,0 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,# 20,20'); + assertInvalidPath('M0,0 A10,10 0 0,2 20,20'); }); test('Check character constants', () { From a74a6f7ea74a9d9eba5830580d8de2a3ea7bafc1 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 6 May 2019 19:14:40 -0700 Subject: [PATCH 06/28] Fixes and bump --- third_party/packages/path_parsing/CHANGELOG.md | 4 ++++ third_party/packages/path_parsing/lib/src/path_parsing.dart | 4 ++-- third_party/packages/path_parsing/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 54519e6e008..2c127f32c8d 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 0.1.4 + +- Fix implementation of `_PathOffset`'s `==` operator. + ## 0.1.3 - Fix a bug in decompose cubic curve - avoid trying to call `toInt()` on `double.infinity` diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 6846f11bf09..992b3a7d1f3 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -77,7 +77,7 @@ class _PathOffset { @override bool operator ==(Object other) { - return other is _PathOffset && other.dx == other.dy; + return other is _PathOffset && other.dx == dx && other.dy == dy; } // TODO(dnfield): Use a real hashing function - but this should at least be better than the default. @@ -703,7 +703,7 @@ class SvgPathNormalizer { final double d = delta.dx * delta.dx + delta.dy * delta.dy; final double scaleFactorSquared = math.max(1.0 / d - 0.25, 0.0); double scaleFactor = math.sqrt(scaleFactorSquared); - if (scaleFactor == double.infinity || scaleFactor == double.negativeInfinity) { + if (!scaleFactor.isFinite) { scaleFactor = 0.0; } diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 94b7ceb390d..d7c4887d594 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,5 +1,5 @@ name: path_parsing -version: 0.1.3 +version: 0.1.4 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. author: Dan Field From f0df45aeb7964b432c87e9de15586d1240725712 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 9 Nov 2020 09:32:00 -0800 Subject: [PATCH 07/28] Null safe (#3) --- .../packages/path_parsing/CHANGELOG.md | 4 + .../path_parsing/analysis_options.yaml | 12 +- .../packages/path_parsing/example/main.dart | 23 ++- .../path_parsing/example/pubspec.lock | 26 +++ .../path_parsing/example/pubspec.yaml | 9 + .../path_parsing/lib/src/path_parsing.dart | 120 +++++------ .../packages/path_parsing/pubspec.lock | 195 +++++++++--------- .../packages/path_parsing/pubspec.yaml | 13 +- .../test/parse_path_deep_test.dart | 11 +- .../path_parsing/test/parse_path_test.dart | 16 +- 10 files changed, 239 insertions(+), 190 deletions(-) create mode 100644 third_party/packages/path_parsing/example/pubspec.lock create mode 100644 third_party/packages/path_parsing/example/pubspec.yaml diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 2c127f32c8d..0d5405b14b4 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 0.2.0-nullsafety.0 + +- Nullsafety migration. + ## 0.1.4 - Fix implementation of `_PathOffset`'s `==` operator. diff --git a/third_party/packages/path_parsing/analysis_options.yaml b/third_party/packages/path_parsing/analysis_options.yaml index 486e3dbdd80..4aa930c6950 100644 --- a/third_party/packages/path_parsing/analysis_options.yaml +++ b/third_party/packages/path_parsing/analysis_options.yaml @@ -20,13 +20,11 @@ # in sync with this file. analyzer: - language: - enableSuperMixins: true + enable-experiment: + - non-nullable strong-mode: implicit-dynamic: false errors: - # treat missing required parameters as a warning (not a hint) - missing_required_param: warning # treat missing returns as a warning (not a hint) missing_return: warning # allow having TODOs in the code @@ -48,7 +46,6 @@ linter: - always_specify_types - annotate_overrides # - avoid_annotating_with_dynamic # conflicts with always_specify_types - - avoid_as # - avoid_bool_literals_in_conditional_expressions # not yet tested # - avoid_catches_without_on_clauses # we do this commonly # - avoid_catching_errors # we do this commonly @@ -104,7 +101,6 @@ linter: # - parameter_assignments # we do this commonly - prefer_adjacent_string_concatenation - prefer_asserts_in_initializer_lists - - prefer_bool_in_asserts - prefer_collection_literals - prefer_conditional_assignment - prefer_const_constructors @@ -129,7 +125,6 @@ linter: - slash_for_doc_comments - sort_constructors_first - sort_unnamed_constructors_first - - super_goes_last - test_types_in_equals - throw_in_finally # - type_annotate_public_apis # subset of always_specify_types @@ -149,4 +144,5 @@ linter: # - use_setters_to_change_properties # not yet tested # - use_string_buffers # https://github.com/dart-lang/linter/pull/664 # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - - valid_regexps \ No newline at end of file + - valid_regexps + - unnecessary_new \ No newline at end of file diff --git a/third_party/packages/path_parsing/example/main.dart b/third_party/packages/path_parsing/example/main.dart index efc3bd3a97d..c5e03a68c75 100644 --- a/third_party/packages/path_parsing/example/main.dart +++ b/third_party/packages/path_parsing/example/main.dart @@ -9,7 +9,13 @@ class PathPrinter extends PathProxy { @override void cubicTo( - double x1, double y1, double x2, double y2, double x3, double y3) { + double x1, + double y1, + double x2, + double y2, + double x3, + double y3, + ) { print('Path.cubicTo($x1, $y1, $x2, $y2, $x3, $y3);'); } @@ -26,7 +32,18 @@ class PathPrinter extends PathProxy { void main() { const String pathData = - 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'; + 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 ' + '-4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 ' + '3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 ' + '10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 ' + '1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 ' + '0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 ' + '21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 ' + '19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 ' + '0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 ' + '15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 ' + '24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 ' + '22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z'; - writeSvgPathDataToPath(pathData, new PathPrinter()); + writeSvgPathDataToPath(pathData, PathPrinter()); } diff --git a/third_party/packages/path_parsing/example/pubspec.lock b/third_party/packages/path_parsing/example/pubspec.lock new file mode 100644 index 00000000000..f5dd70baa2c --- /dev/null +++ b/third_party/packages/path_parsing/example/pubspec.lock @@ -0,0 +1,26 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0-nullsafety.6" + path_parsing: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.2.0-nullsafety.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0-nullsafety.5" +sdks: + dart: ">=2.12.0-0 <3.0.0" diff --git a/third_party/packages/path_parsing/example/pubspec.yaml b/third_party/packages/path_parsing/example/pubspec.yaml new file mode 100644 index 00000000000..f854e67d461 --- /dev/null +++ b/third_party/packages/path_parsing/example/pubspec.yaml @@ -0,0 +1,9 @@ +name: path_parsing_example +publish_to: none + +dependencies: + path_parsing: + path: ../ + +environment: + sdk: '>=2.12.0-0 <3.0.0' diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 992b3a7d1f3..66dc56ee957 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -18,13 +18,13 @@ import 'package:vector_math/vector_math.dart' show Matrix4; import './path_segment_type.dart'; /// Parse `svg`, emitting the segment data to `path`. -void writeSvgPathDataToPath(String svg, PathProxy path) { +void writeSvgPathDataToPath(String? svg, PathProxy path) { if (svg == null || svg == '') { return; } - final SvgPathStringSource parser = new SvgPathStringSource(svg); - final SvgPathNormalizer normalizer = new SvgPathNormalizer(); + final SvgPathStringSource parser = SvgPathStringSource(svg); + final SvgPathNormalizer normalizer = SvgPathNormalizer(); for (PathSegmentData seg in parser.parseSegments()) { normalizer.emitSegment(seg, path); } @@ -50,8 +50,8 @@ abstract class PathProxy { @immutable class _PathOffset { const _PathOffset(this.dx, this.dy) - : assert(dx != null), - assert(dy != null); + : assert(dx != null), // ignore: unnecessary_null_comparison + assert(dy != null); // ignore: unnecessary_null_comparison static _PathOffset get zero => const _PathOffset(0.0, 0.0); final double dx; @@ -60,20 +60,18 @@ class _PathOffset { double get direction => math.atan2(dy, dx); _PathOffset translate(double translateX, double translateY) => - new _PathOffset(dx + translateX, dy + translateY); + _PathOffset(dx + translateX, dy + translateY); _PathOffset operator +(_PathOffset other) => - new _PathOffset(dx + other.dx, dy + other.dy); + _PathOffset(dx + other.dx, dy + other.dy); _PathOffset operator -(_PathOffset other) => - new _PathOffset(dx - other.dx, dy - other.dy); + _PathOffset(dx - other.dx, dy - other.dy); _PathOffset operator *(double operand) => - new _PathOffset(dx * operand, dy * operand); + _PathOffset(dx * operand, dy * operand); @override - String toString() { - return 'PathOffset{$dx,$dy}'; - } + String toString() => 'PathOffset{$dx,$dy}'; @override bool operator ==(Object other) { @@ -89,15 +87,16 @@ const double _twoPiFloat = math.pi * 2.0; const double _piOverTwoFloat = math.pi / 2.0; class SvgPathStringSource { - SvgPathStringSource(String string) : assert(string != null) { - _previousCommand = SvgPathSegType.unknown; - _codePoints = string.codeUnits; - _idx = 0; + SvgPathStringSource(String string) + : assert(string != null), // ignore: unnecessary_null_comparison + _previousCommand = SvgPathSegType.unknown, + _codePoints = string.codeUnits, + _idx = 0 { _skipOptionalSvgSpaces(); } SvgPathSegType _previousCommand; - List _codePoints; + final List _codePoints; int _idx; bool _isHtmlSpace(int character) { @@ -153,7 +152,9 @@ class SvgPathStringSource { } SvgPathSegType _maybeImplicitCommand( - int lookahead, SvgPathSegType nextCommand) { + int lookahead, + SvgPathSegType nextCommand, + ) { // Check if the current lookahead may start a number - in which case it // could be the start of an implicit command. The 'close' command does not // have any parameters though and hence can't have an implicit @@ -199,8 +200,7 @@ class SvgPathStringSource { _codePoints[_idx] > AsciiConstants.number9) && _codePoints[_idx] != AsciiConstants.period)) // The first character of a number must be one of [0-9+-.] - throw new StateError( - 'First character of a number must be one of [0-9+-.]'); + throw StateError('First character of a number must be one of [0-9+-.]'); // read the integer part, build right-to-left final int digitsStart = _idx; @@ -221,7 +221,7 @@ class SvgPathStringSource { } // Bail out early if this overflows. if (!_isValidRange(integer)) { - throw new StateError('Numeric overflow'); + throw StateError('Numeric overflow'); } } @@ -234,8 +234,7 @@ class SvgPathStringSource { if (_idx >= end || _codePoints[_idx] < AsciiConstants.number0 || _codePoints[_idx] > AsciiConstants.number9) - throw new StateError( - 'There must be at least one digit following the .'); + throw StateError('There must be at least one digit following the .'); double frac = 1.0; while (_idx < end && @@ -274,7 +273,7 @@ class SvgPathStringSource { if (_idx >= end || _codePoints[_idx] < AsciiConstants.number0 || _codePoints[_idx] > AsciiConstants.number9) - throw new StateError('Missing exponent'); + throw StateError('Missing exponent'); double exponent = 0.0; while (_idx < end && @@ -289,7 +288,7 @@ class SvgPathStringSource { } // Make sure exponent is valid. if (!_isValidExponent(exponent)) { - throw new StateError('Invalid exponent $exponent'); + throw StateError('Invalid exponent $exponent'); } if (exponent != 0) { number *= math.pow(10.0, exponent); @@ -298,7 +297,7 @@ class SvgPathStringSource { // Don't return Infinity() or NaN(). if (!_isValidRange(number)) { - throw new StateError('Numeric overflow'); + throw StateError('Numeric overflow'); } // if (mode & kAllowTrailingWhitespace) @@ -309,7 +308,7 @@ class SvgPathStringSource { bool _parseArcFlag() { if (!hasMoreData) { - throw new StateError('Expected more data'); + throw StateError('Expected more data'); } final int flagChar = _codePoints[_idx]; _idx++; @@ -320,7 +319,7 @@ class SvgPathStringSource { else if (flagChar == AsciiConstants.number1) return true; else - throw new StateError('Invalid flag value'); + throw StateError('Invalid flag value'); } bool get hasMoreData => _idx < _codePoints.length; @@ -333,16 +332,14 @@ class SvgPathStringSource { PathSegmentData parseSegment() { assert(hasMoreData); - final PathSegmentData segment = new PathSegmentData(); + final PathSegmentData segment = PathSegmentData(); final int lookahead = _codePoints[_idx]; SvgPathSegType command = AsciiConstants.mapLetterToSegmentType(lookahead); if (_previousCommand == SvgPathSegType.unknown) { // First command has to be a moveto. if (command != SvgPathSegType.moveToRel && command != SvgPathSegType.moveToAbs) { - throw new StateError('Expected to find moveTo command'); - // SetErrorMark(SVGParseStatus::kExpectedMoveToCommand); - // return segment; + throw StateError('Expected to find moveTo command'); } // Consume command letter. _idx++; @@ -350,8 +347,8 @@ class SvgPathStringSource { // Possibly an implicit command. assert(_previousCommand != SvgPathSegType.unknown); command = _maybeImplicitCommand(lookahead, command); - if (command == null || command == SvgPathSegType.unknown) { - throw new StateError('Expected a path command'); + if (command == SvgPathSegType.unknown) { + throw StateError('Expected a path command'); } } else { // Valid explicit command. @@ -363,12 +360,12 @@ class SvgPathStringSource { switch (segment.command) { case SvgPathSegType.cubicToRel: case SvgPathSegType.cubicToAbs: - segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); + segment.point1 = _PathOffset(_parseNumber(), _parseNumber()); continue cubic_smooth; case SvgPathSegType.smoothCubicToRel: cubic_smooth: case SvgPathSegType.smoothCubicToAbs: - segment.point2 = new _PathOffset(_parseNumber(), _parseNumber()); + segment.point2 = _PathOffset(_parseNumber(), _parseNumber()); continue quad_smooth; case SvgPathSegType.moveToRel: case SvgPathSegType.moveToAbs: @@ -377,36 +374,36 @@ class SvgPathStringSource { case SvgPathSegType.smoothQuadToRel: quad_smooth: case SvgPathSegType.smoothQuadToAbs: - segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); break; case SvgPathSegType.lineToHorizontalRel: case SvgPathSegType.lineToHorizontalAbs: segment.targetPoint = - new _PathOffset(_parseNumber(), segment.targetPoint?.dy ?? 0.0); + _PathOffset(_parseNumber(), segment.targetPoint.dy); break; case SvgPathSegType.lineToVerticalRel: case SvgPathSegType.lineToVerticalAbs: segment.targetPoint = - new _PathOffset(segment.targetPoint?.dx ?? 0.0, _parseNumber()); + _PathOffset(segment.targetPoint.dx, _parseNumber()); break; case SvgPathSegType.close: _skipOptionalSvgSpaces(); break; case SvgPathSegType.quadToRel: case SvgPathSegType.quadToAbs: - segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); - segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + segment.point1 = _PathOffset(_parseNumber(), _parseNumber()); + segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); break; case SvgPathSegType.arcToRel: case SvgPathSegType.arcToAbs: - segment.point1 = new _PathOffset(_parseNumber(), _parseNumber()); + segment.point1 = _PathOffset(_parseNumber(), _parseNumber()); segment.arcAngle = _parseNumber(); segment.arcLarge = _parseArcFlag(); segment.arcSweep = _parseArcFlag(); - segment.targetPoint = new _PathOffset(_parseNumber(), _parseNumber()); + segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); break; case SvgPathSegType.unknown: - throw new StateError('Unknown segment command'); + throw StateError('Unknown segment command'); } return segment; @@ -416,7 +413,7 @@ class SvgPathStringSource { class OffsetHelper { static _PathOffset reflectedPoint( _PathOffset reflectedIn, _PathOffset pointToReflect) { - return new _PathOffset(2 * reflectedIn.dx - pointToReflect.dx, + return _PathOffset(2 * reflectedIn.dx - pointToReflect.dx, 2 * reflectedIn.dy - pointToReflect.dy); } @@ -424,7 +421,7 @@ class OffsetHelper { /// Blend the points with a ratio (1/3):(2/3). static _PathOffset blendPoints(_PathOffset p1, _PathOffset p2) { - return new _PathOffset((p1.dx + 2 * p2.dx) * _kOneOverThree, + return _PathOffset((p1.dx + 2 * p2.dx) * _kOneOverThree, (p1.dy + 2 * p2.dy) * _kOneOverThree); } } @@ -454,8 +451,7 @@ class PathSegmentData { _PathOffset get arcRadii => point1; double get arcAngle => point2.dx; - set arcAngle(double angle) => - point2 = new _PathOffset(angle, point2?.dy ?? 0.0); + set arcAngle(double angle) => point2 = _PathOffset(angle, point2.dy); double get r1 => arcRadii.dx; double get r2 => arcRadii.dy; @@ -473,9 +469,9 @@ class PathSegmentData { double get y2 => point2.dy; SvgPathSegType command; - _PathOffset targetPoint; - _PathOffset point1; - _PathOffset point2; + _PathOffset targetPoint = _PathOffset.zero; + _PathOffset point1 = _PathOffset.zero; + _PathOffset point2 = _PathOffset.zero; bool arcSweep; bool arcLarge; @@ -493,9 +489,7 @@ class SvgPathNormalizer { void emitSegment(PathSegmentData segment, PathProxy path) { final PathSegmentData normSeg = segment; - assert( - normSeg.command == SvgPathSegType.close || normSeg.targetPoint != null); - assert(_currentPoint != null); + assert(_currentPoint != null); // ignore: unnecessary_null_comparison // Convert relative points to absolute points. switch (segment.command) { case SvgPathSegType.quadToRel: @@ -520,11 +514,11 @@ class SvgPathNormalizer { break; case SvgPathSegType.lineToHorizontalAbs: normSeg.targetPoint = - new _PathOffset(normSeg.targetPoint.dx, _currentPoint.dy); + _PathOffset(normSeg.targetPoint.dx, _currentPoint.dy); break; case SvgPathSegType.lineToVerticalAbs: normSeg.targetPoint = - new _PathOffset(_currentPoint.dx, normSeg.targetPoint.dy); + _PathOffset(_currentPoint.dx, normSeg.targetPoint.dy); break; case SvgPathSegType.close: // Reset m_currentPoint for the next path. @@ -626,7 +620,7 @@ class SvgPathNormalizer { } break; default: - throw new StateError('Invalid command type in path'); + throw StateError('Invalid command type in path'); } _currentPoint = normSeg.targetPoint; @@ -668,12 +662,12 @@ class SvgPathNormalizer { final _PathOffset midPointDistance = (currentPoint - arcSegment.targetPoint) * 0.5; - final Matrix4 pointTransform = new Matrix4.identity(); + final Matrix4 pointTransform = Matrix4.identity(); pointTransform.rotateZ(-angle); final _PathOffset transformedMidPoint = _mapPoint( pointTransform, - new _PathOffset( + _PathOffset( midPointDistance.dx, midPointDistance.dy, ), @@ -747,17 +741,17 @@ class SvgPathNormalizer { final double sinEndTheta = math.sin(endTheta); final double cosEndTheta = math.cos(endTheta); - point1 = new _PathOffset( + point1 = _PathOffset( cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta, ).translate(centerPoint.dx, centerPoint.dy); - final _PathOffset targetPoint = new _PathOffset( + final _PathOffset targetPoint = _PathOffset( cosEndTheta, sinEndTheta, ).translate(centerPoint.dx, centerPoint.dy); point2 = targetPoint.translate(t * sinEndTheta, -t * cosEndTheta); - final PathSegmentData cubicSegment = new PathSegmentData(); + final PathSegmentData cubicSegment = PathSegmentData(); cubicSegment.command = SvgPathSegType.cubicToAbs; cubicSegment.point1 = _mapPoint(pointTransform, point1); cubicSegment.point2 = _mapPoint(pointTransform, point2); @@ -772,7 +766,7 @@ class SvgPathNormalizer { _PathOffset _mapPoint(Matrix4 transform, _PathOffset point) { // a, b, 0.0, 0.0, c, d, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, e, f, 0.0, 1.0 - return new _PathOffset( + return _PathOffset( transform.storage[0] * point.dx + transform.storage[4] * point.dy + transform.storage[12], diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock index 2cbffe08729..55305b0c97f 100644 --- a/third_party/packages/path_parsing/pubspec.lock +++ b/third_party/packages/path_parsing/pubspec.lock @@ -1,237 +1,216 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "12.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.33.1" + version: "0.40.6" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.0" + version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.5.0-nullsafety.3" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" - collection: + version: "1.2.0-nullsafety.3" + cli_util: dependency: transitive description: - name: collection + name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" - convert: + version: "0.2.0" + collection: dependency: transitive description: - name: convert + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" - crypto: + version: "1.15.0-nullsafety.5" + convert: dependency: transitive description: - name: crypto + name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" - csslib: + version: "2.1.1" + coverage: dependency: transitive description: - name: csslib + name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.6" - front_end: + version: "0.14.1" + crypto: dependency: transitive description: - name: front_end + name: crypto url: "https://pub.dartlang.org" source: hosted - version: "0.1.6+1" + version: "2.1.5" glob: dependency: transitive description: name: glob url: "https://pub.dartlang.org" source: hosted - version: "1.1.7" - html: - dependency: transitive - description: - name: html - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.3+3" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.0" + version: "1.2.0" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.2.0" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" + version: "3.1.4" io: dependency: transitive description: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "0.3.4" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.1+1" - json_rpc_2: - dependency: transitive - description: - name: json_rpc_2 - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.9" - kernel: - dependency: transitive - description: - name: kernel - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.6+1" + version: "0.6.3-nullsafety.3" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.3+2" + version: "0.11.4" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.3+1" + version: "0.12.10-nullsafety.3" meta: dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.6" mime: dependency: transitive description: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.6+2" - multi_server_socket: + version: "0.9.7" + node_interop: dependency: transitive description: - name: multi_server_socket + name: node_interop url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" - node_preamble: + version: "1.2.0" + node_io: dependency: transitive description: - name: node_preamble + name: node_io url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" - package_config: + version: "1.1.1" + node_preamble: dependency: transitive description: - name: package_config + name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" - package_resolver: + version: "1.4.12" + package_config: dependency: transitive description: - name: package_resolver + name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.0.6" + version: "1.9.3" path: dependency: "direct dev" description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" - plugin: + version: "1.8.0-nullsafety.3" + pedantic: dependency: transitive description: - name: plugin + name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+3" + version: "1.10.0-nullsafety.3" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.3.6" + version: "1.5.0-nullsafety.3" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.2" + version: "1.4.4" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.3+3" + version: "0.7.9" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0" shelf_static: dependency: transitive description: @@ -245,111 +224,125 @@ packages: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.2+4" + version: "0.2.3" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.1.5" + version: "2.1.0-nullsafety.4" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.8" + version: "0.10.10-nullsafety.3" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.4.1" + version: "1.8.0-nullsafety.4" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety.6" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "1.6.8" + version: "2.1.0-nullsafety.3" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.1.0-nullsafety.3" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.2.0-nullsafety.3" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.3.4" - typed_data: + version: "1.16.0-nullsafety.9" + test_api: dependency: transitive description: - name: typed_data + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.19-nullsafety.6" + test_core: + dependency: transitive + description: + name: test_core url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" - utf: + version: "0.3.12-nullsafety.9" + typed_data: dependency: transitive description: - name: utf + name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "0.9.0+5" + version: "1.3.0-nullsafety.5" vector_math: dependency: "direct main" description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - vm_service_client: + version: "2.1.0-nullsafety.5" + vm_service: dependency: transitive description: - name: vm_service_client + name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "0.2.6" + version: "5.5.0" watcher: dependency: transitive description: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+10" + version: "0.9.7+15" web_socket_channel: dependency: transitive description: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.0.9" + version: "1.1.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.4" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.1.15" + version: "2.2.1" sdks: - dart: ">=2.0.0 <3.0.0" + dart: ">=2.12.0-0.0 <3.0.0" diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index d7c4887d594..45a47513f60 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,17 +1,16 @@ name: path_parsing -version: 0.1.4 +version: 0.2.0-nullsafety.0 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. -author: Dan Field homepage: https://github.com/dnfield/dart_path_parsing dependencies: - vector_math: ">=2.0.6 <3.0.0" - meta: ">=1.1.2 <2.0.0" + vector_math: ^2.1.0-nullsafety.3 + meta: ^1.3.0-nullsafety.4 dev_dependencies: - path: ^1.5.1 - test: ^1.3.4 + path: ^1.8.0-nullsafety.1 + test: ^1.16.0-nullsafety.9 environment: - sdk: ">=1.19.0 <3.0.0" \ No newline at end of file + sdk: '>=2.12.0-0 <3.0.0' diff --git a/third_party/packages/path_parsing/test/parse_path_deep_test.dart b/third_party/packages/path_parsing/test/parse_path_deep_test.dart index b23cf214c71..e73391bc9e8 100644 --- a/third_party/packages/path_parsing/test/parse_path_deep_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_deep_test.dart @@ -1,7 +1,6 @@ import 'package:path_parsing/path_parsing.dart'; import 'package:test/test.dart'; - class DeepTestPathProxy extends PathProxy { DeepTestPathProxy(this.expectedCommands); @@ -15,7 +14,13 @@ class DeepTestPathProxy extends PathProxy { @override void cubicTo( - double x1, double y1, double x2, double y2, double x3, double y3) { + double x1, + double y1, + double x2, + double y2, + double x3, + double y3, + ) { actualCommands.add('cubicTo($x1, $y1, $x2, $y2, $x3, $y3)'); } @@ -36,7 +41,7 @@ class DeepTestPathProxy extends PathProxy { void main() { void assertValidPath(String input, List commands) { - final DeepTestPathProxy proxy = new DeepTestPathProxy(commands); + final DeepTestPathProxy proxy = DeepTestPathProxy(commands); writeSvgPathDataToPath(input, proxy); proxy.validate(); } diff --git a/third_party/packages/path_parsing/test/parse_path_test.dart b/third_party/packages/path_parsing/test/parse_path_test.dart index 631ff4aab17..72c4e370efa 100644 --- a/third_party/packages/path_parsing/test/parse_path_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_test.dart @@ -16,7 +16,13 @@ class TestPathProxy extends PathProxy { @override void cubicTo( - double x1, double y1, double x2, double y2, double x3, double y3) { + double x1, + double y1, + double x2, + double y2, + double x3, + double y3, + ) { called = true; } @@ -33,15 +39,15 @@ class TestPathProxy extends PathProxy { void main() { void assertValidPath(String input) { - final TestPathProxy proxy = new TestPathProxy(); + final TestPathProxy proxy = TestPathProxy(); // these shouldn't throw or assert writeSvgPathDataToPath(input, proxy); expect(proxy.called, true); } void assertInvalidPath(String input) { - expect(() => writeSvgPathDataToPath(input, new TestPathProxy()), - throwsStateError); + expect( + () => writeSvgPathDataToPath(input, TestPathProxy()), throwsStateError); } test('Valid Paths', () { @@ -77,7 +83,7 @@ void main() { assertValidPath('M100,200 a3,4,5,106,7'); assertValidPath('M100,200 a3,4,5,116,7'); assertValidPath( - '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 + '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); assertValidPath( From 6d0d265c7e07d9d5a2c8fabda9b52940f17f3a49 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 9 Nov 2020 09:36:14 -0800 Subject: [PATCH 08/28] Null safe (#4) --- third_party/packages/path_parsing/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/third_party/packages/path_parsing/analysis_options.yaml b/third_party/packages/path_parsing/analysis_options.yaml index 4aa930c6950..d23cbd0c131 100644 --- a/third_party/packages/path_parsing/analysis_options.yaml +++ b/third_party/packages/path_parsing/analysis_options.yaml @@ -20,8 +20,6 @@ # in sync with this file. analyzer: - enable-experiment: - - non-nullable strong-mode: implicit-dynamic: false errors: From efb8ea7bc8d422e5f5dae2c269bff9f2e1b5412e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 9 Nov 2020 13:52:02 -0800 Subject: [PATCH 09/28] cirrus --- third_party/packages/path_parsing/.cirrus.yml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 third_party/packages/path_parsing/.cirrus.yml diff --git a/third_party/packages/path_parsing/.cirrus.yml b/third_party/packages/path_parsing/.cirrus.yml new file mode 100644 index 00000000000..34c0d628be4 --- /dev/null +++ b/third_party/packages/path_parsing/.cirrus.yml @@ -0,0 +1,28 @@ +container: + image: cirrusci/flutter:latest + +env: + CI_NAME: "CirrusCI" + CI_BUILD_NUMBER: $CIRRUS_TASK_ID + CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID" + CI_BRANCH: $CIRRUS_BRANCH + CI_PULL_REQUEST: $CIRRUS_PR + COVERALLS_REPO_TOKEN: ENCRYPTED[61ba3fee193a9ed6116e0f61bbe26fe8c0452287e5dfd86c728e2f1f24327818d6c74c956d7b9cbf3bd6236489af0fd1] + +test_task: + matrix: + - name: stable + channel_script: | + flutter channel stable + flutter upgrade + - name: master + channel_script: | + flutter channel master + flutter upgrade + pub_cache: + folder: ~/.pub-cache + analyze_script: flutter analyze . + test_script: flutter test --coverage + coveralls_script: | + dart pub global activate coveralls + dart pub global run coveralls coverage/lcov.info From d1739c414d89cb2a110c1b2ad5c2c95920c8df6b Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 6 Apr 2021 16:10:46 -0700 Subject: [PATCH 10/28] Nullsafe stable release --- .../packages/path_parsing/CHANGELOG.md | 4 + .../packages/path_parsing/pubspec.lock | 117 ++++++++---------- .../packages/path_parsing/pubspec.yaml | 12 +- 3 files changed, 65 insertions(+), 68 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 0d5405b14b4..e606ce6bf9c 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 0.2.0 + +- Stable nullsafe release + ## 0.2.0-nullsafety.0 - Nullsafety migration. diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock index 55305b0c97f..c28f3ab60ef 100644 --- a/third_party/packages/path_parsing/pubspec.lock +++ b/third_party/packages/path_parsing/pubspec.lock @@ -7,342 +7,335 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "12.0.0" + version: "19.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.40.6" + version: "1.3.0" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" + version: "2.0.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.3" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.0" cli_util: dependency: transitive description: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.3.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.5" + version: "1.15.0" convert: dependency: transitive description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "3.0.0" coverage: dependency: transitive description: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.1" + version: "1.0.2" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "3.0.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" glob: dependency: transitive description: name: glob url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "2.0.1" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.0.0" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" io: dependency: transitive description: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "1.0.0" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.3" + version: "0.6.3" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.4" + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.3" + version: "0.12.10" meta: dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.6" + version: "1.3.0" mime: dependency: transitive description: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.7" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - node_io: - dependency: transitive - description: - name: node_io - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" + version: "1.0.0" node_preamble: dependency: transitive description: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.4.12" + version: "2.0.0" package_config: dependency: transitive description: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "2.0.0" path: dependency: "direct dev" description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.3" + version: "1.8.0" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.3" + version: "1.11.0" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.5.0-nullsafety.3" + version: "1.5.0" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "2.0.0" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.9" + version: "1.1.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "3.0.0" shelf_static: dependency: transitive description: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "0.2.8" + version: "1.0.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.3" + version: "1.0.1" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.4" + version: "2.1.0" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.10-nullsafety.3" + version: "0.10.10" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.4" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.6" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.0" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.0-nullsafety.9" + version: "1.16.8" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.6" + version: "0.3.0" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.12-nullsafety.9" + version: "0.3.19" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.5" + version: "1.3.0" vector_math: dependency: "direct main" description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.5" + version: "2.1.0" vm_service: dependency: transitive description: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "5.5.0" + version: "6.2.0" watcher: dependency: transitive description: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+15" + version: "1.0.0" web_socket_channel: dependency: transitive description: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "2.0.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.4" + version: "1.0.0" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.1.0" sdks: - dart: ">=2.12.0-0.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 45a47513f60..79c4d1ffd9b 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,16 +1,16 @@ name: path_parsing -version: 0.2.0-nullsafety.0 +version: 0.2.0 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. homepage: https://github.com/dnfield/dart_path_parsing dependencies: - vector_math: ^2.1.0-nullsafety.3 - meta: ^1.3.0-nullsafety.4 + vector_math: ^2.1.0 + meta: ^1.3.0 dev_dependencies: - path: ^1.8.0-nullsafety.1 - test: ^1.16.0-nullsafety.9 + path: ^1.8.0 + test: ^1.16.0 environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' From 1c57912fe6048f18abca5d1618f13bf5c567287f Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 5 May 2021 00:34:05 -0700 Subject: [PATCH 11/28] Update .cirrus.yml (#7) --- third_party/packages/path_parsing/.cirrus.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/third_party/packages/path_parsing/.cirrus.yml b/third_party/packages/path_parsing/.cirrus.yml index 34c0d628be4..c9ee69af152 100644 --- a/third_party/packages/path_parsing/.cirrus.yml +++ b/third_party/packages/path_parsing/.cirrus.yml @@ -1,24 +1,16 @@ -container: - image: cirrusci/flutter:latest - env: CI_NAME: "CirrusCI" CI_BUILD_NUMBER: $CIRRUS_TASK_ID CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID" CI_BRANCH: $CIRRUS_BRANCH CI_PULL_REQUEST: $CIRRUS_PR - COVERALLS_REPO_TOKEN: ENCRYPTED[61ba3fee193a9ed6116e0f61bbe26fe8c0452287e5dfd86c728e2f1f24327818d6c74c956d7b9cbf3bd6236489af0fd1] + COVERALLS_REPO_TOKEN: ENCRYPTED[818fc7b63ab15e18ff5f9813b9983dba79ffb6a9a21861f7797096c0522e0b7ad07fa0b994f87d8187da8f8f9ce3b8ef] test_task: - matrix: - - name: stable - channel_script: | - flutter channel stable - flutter upgrade - - name: master - channel_script: | - flutter channel master - flutter upgrade + container: + matrix: + - image: cirrusci/flutter:dev + - image: cirrusci/flutter:stable pub_cache: folder: ~/.pub-cache analyze_script: flutter analyze . From 9eb9ad5cf0d603dd41956f3fbbe2716b9155ed49 Mon Sep 17 00:00:00 2001 From: jefflim-google <52889965+jefflim-google@users.noreply.github.com> Date: Wed, 5 May 2021 15:41:32 +0800 Subject: [PATCH 12/28] Improve path_parsing performance. (#6) * Improve path_parsing performance. This code: * Avoiding String.codeUnits. * Reduces lookups to String.codeUnitAt * Caches _length * Builds integer value in a single pass. String.codeUnits on both JS and VM returns a forwarding CodeUnits class defined here, so all lookups to codeUnits[index] actually go through an extra layer of dispatch. Combined, all of these changes improve the parsing speed by ~25% when measured with real SVG path data. parseSvgPathData() timing, measured on a Nexus 2 downclocked to 1GHz. Before: Run1: 76,124,392 us Run2: 75,103,426 us Run3: 75,481,128 us After: Run1: 59,319,622 us Run2: 58,435,315 us Run3: 58,478,007 us * analysis cleanup Co-authored-by: Dan Field --- .../path_parsing/lib/src/path_parsing.dart | 188 +++++++++--------- 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 66dc56ee957..4dba1d6a5c7 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -87,17 +87,19 @@ const double _twoPiFloat = math.pi * 2.0; const double _piOverTwoFloat = math.pi / 2.0; class SvgPathStringSource { - SvgPathStringSource(String string) - : assert(string != null), // ignore: unnecessary_null_comparison + SvgPathStringSource(this._string) + : assert(_string != null), // ignore: unnecessary_null_comparison _previousCommand = SvgPathSegType.unknown, - _codePoints = string.codeUnits, - _idx = 0 { + _idx = 0, + _length = _string.length { _skipOptionalSvgSpaces(); } + final String _string; + SvgPathSegType _previousCommand; - final List _codePoints; int _idx; + final int _length; bool _isHtmlSpace(int character) { // Histogram from Apple's page load test combined with some ad hoc browsing @@ -120,30 +122,34 @@ class SvgPathStringSource { character == AsciiConstants.slashF); } - bool _skipOptionalSvgSpaces() { - while (_idx < _codePoints.length && _isHtmlSpace(_codePoints[_idx])) { + /// Increments _idx to the first non-space character. + /// + /// Returns the code unit of the first non-space, or -1 if at end of string. + int _skipOptionalSvgSpaces() { + while (true) { + if (_idx >= _length) { + return -1; + } + + final int c = _string.codeUnitAt(_idx); + if (!_isHtmlSpace(c)) { + return c; + } + _idx++; } - return _idx < _codePoints.length; } - bool _skipOptionalSvgSpacesOrDelimiter( + void _skipOptionalSvgSpacesOrDelimiter( [int delimiter = AsciiConstants.comma]) { - if (_idx < _codePoints.length && - !_isHtmlSpace(_codePoints[_idx]) && - _codePoints[_idx] != delimiter) { - return false; - } - if (_skipOptionalSvgSpaces()) { - if (_idx < _codePoints.length && _codePoints[_idx] == delimiter) { - _idx++; - _skipOptionalSvgSpaces(); - } + final int c = _skipOptionalSvgSpaces(); + if (c == delimiter) { + _idx++; + _skipOptionalSvgSpaces(); } - return _idx < _codePoints.length; } - bool _isNumberStart(int lookahead) { + static bool _isNumberStart(int lookahead) { return (lookahead >= AsciiConstants.number0 && lookahead <= AsciiConstants.number9) || lookahead == AsciiConstants.plus || @@ -171,12 +177,20 @@ class SvgPathStringSource { return _previousCommand; } - bool _isValidRange(double x) { - return x >= -double.maxFinite && x <= double.maxFinite; - } + bool _isValidRange(double x) => + -double.maxFinite <= x && x <= double.maxFinite; - bool _isValidExponent(double x) { - return x >= -37 && x <= 38; + bool _isValidExponent(double x) => + -37 <= x && x <= 38; + + /// Reads a code unit and advances the index. + /// + /// Returns -1 if at end of string. + int _readCodeUnit() { + if (_idx >= _length) { + return -1; + } + return _string.codeUnitAt(_idx++); } // We use this generic parseNumber function to allow the Path parsing code to @@ -185,103 +199,80 @@ class SvgPathStringSource { double _parseNumber() { _skipOptionalSvgSpaces(); - // read the sign + // Read the sign. int sign = 1; - final int end = _codePoints.length; - if (_idx < end && _codePoints[_idx] == AsciiConstants.plus) - _idx++; - else if (_idx < end && _codePoints[_idx] == AsciiConstants.minus) { - _idx++; + int c = _readCodeUnit(); + if (c == AsciiConstants.plus) { + c = _readCodeUnit(); + } else if (c == AsciiConstants.minus) { sign = -1; + c = _readCodeUnit(); } - if (_idx == end || - ((_codePoints[_idx] < AsciiConstants.number0 || - _codePoints[_idx] > AsciiConstants.number9) && - _codePoints[_idx] != AsciiConstants.period)) - // The first character of a number must be one of [0-9+-.] - throw StateError('First character of a number must be one of [0-9+-.]'); - - // read the integer part, build right-to-left - final int digitsStart = _idx; - while (_idx < end && - _codePoints[_idx] >= AsciiConstants.number0 && - _codePoints[_idx] <= AsciiConstants.number9) - ++_idx; // Advance to first non-digit. + if ((c < AsciiConstants.number0 || c > AsciiConstants.number9) + && c != AsciiConstants.period) { + throw StateError('First character of a number must be one of [0-9+-.].'); + } + // Read the integer part, build left-to-right. double integer = 0.0; - if (_idx != digitsStart) { - int ptrScanIntPart = _idx - 1; - int multiplier = 1; - while (ptrScanIntPart >= digitsStart) { - integer += multiplier * - (_codePoints[ptrScanIntPart--] - AsciiConstants.number0); - - multiplier *= 10; - } - // Bail out early if this overflows. - if (!_isValidRange(integer)) { - throw StateError('Numeric overflow'); - } + while (AsciiConstants.number0 <= c && c <= AsciiConstants.number9) { + integer = integer * 10 + (c - AsciiConstants.number0); + c = _readCodeUnit(); + } + + // Bail out early if this overflows. + if (!_isValidRange(integer)) { + throw StateError('Numeric overflow'); } double decimal = 0.0; - if (_idx < end && _codePoints[_idx] == AsciiConstants.period) { + if (c == AsciiConstants.period) { // read the decimals - _idx++; + c = _readCodeUnit(); // There must be a least one digit following the . - if (_idx >= end || - _codePoints[_idx] < AsciiConstants.number0 || - _codePoints[_idx] > AsciiConstants.number9) + if (c < AsciiConstants.number0 || + c > AsciiConstants.number9) throw StateError('There must be at least one digit following the .'); double frac = 1.0; - while (_idx < end && - _codePoints[_idx] >= AsciiConstants.number0 && - _codePoints[_idx] <= AsciiConstants.number9) { + while (AsciiConstants.number0 <= c && c <= AsciiConstants.number9) { frac *= 0.1; - decimal += (_codePoints[_idx++] - AsciiConstants.number0) * frac; + decimal += (c - AsciiConstants.number0) * frac; + c = _readCodeUnit(); } } - // When we get here we should have consumed either a digit for the integer - // part or a fractional part (with at least one digit after the '.'.) - assert(digitsStart != _idx); - double number = integer + decimal; number *= sign; // read the exponent part - if (_idx + 1 < end && - (_codePoints[_idx] == AsciiConstants.lowerE || - _codePoints[_idx] == AsciiConstants.upperE) && - (_codePoints[_idx + 1] != AsciiConstants.lowerX && - _codePoints[_idx + 1] != AsciiConstants.lowerM)) { - _idx++; + if (_idx < _length && + (c == AsciiConstants.lowerE || c == AsciiConstants.upperE) && + (_string.codeUnitAt(_idx) != AsciiConstants.lowerX && + _string.codeUnitAt(_idx) != AsciiConstants.lowerM)) { + c = _readCodeUnit(); // read the sign of the exponent bool exponentIsNegative = false; - if (_codePoints[_idx] == AsciiConstants.plus) - _idx++; - else if (_codePoints[_idx] == AsciiConstants.minus) { - _idx++; + if (c == AsciiConstants.plus) { + c = _readCodeUnit(); + } else if (c == AsciiConstants.minus) { + c = _readCodeUnit(); exponentIsNegative = true; } // There must be an exponent - if (_idx >= end || - _codePoints[_idx] < AsciiConstants.number0 || - _codePoints[_idx] > AsciiConstants.number9) + if (c < AsciiConstants.number0 || + c > AsciiConstants.number9) throw StateError('Missing exponent'); double exponent = 0.0; - while (_idx < end && - _codePoints[_idx] >= AsciiConstants.number0 && - _codePoints[_idx] <= AsciiConstants.number9) { + while (c >= AsciiConstants.number0 && c <= AsciiConstants.number9) { exponent *= 10.0; - exponent += _codePoints[_idx] - AsciiConstants.number0; - _idx++; + exponent += c - AsciiConstants.number0; + c = _readCodeUnit(); } if (exponentIsNegative) { exponent = -exponent; @@ -300,9 +291,17 @@ class SvgPathStringSource { throw StateError('Numeric overflow'); } - // if (mode & kAllowTrailingWhitespace) - _skipOptionalSvgSpacesOrDelimiter(); + // At this stage, c contains an unprocessed character, and _idx has + // already been incremented. + + // If c == -1, the input was already at the end of the string, so no + // further processing needs to occur. + if (c != -1) { + --_idx; // Put the unprocessed character back. + // if (mode & kAllowTrailingWhitespace) + _skipOptionalSvgSpacesOrDelimiter(); + } return number; } @@ -310,8 +309,7 @@ class SvgPathStringSource { if (!hasMoreData) { throw StateError('Expected more data'); } - final int flagChar = _codePoints[_idx]; - _idx++; + final int flagChar = _string.codeUnitAt(_idx++); _skipOptionalSvgSpacesOrDelimiter(); if (flagChar == AsciiConstants.number0) @@ -322,7 +320,7 @@ class SvgPathStringSource { throw StateError('Invalid flag value'); } - bool get hasMoreData => _idx < _codePoints.length; + bool get hasMoreData => _idx < _length; Iterable parseSegments() sync* { while (hasMoreData) { @@ -333,7 +331,7 @@ class SvgPathStringSource { PathSegmentData parseSegment() { assert(hasMoreData); final PathSegmentData segment = PathSegmentData(); - final int lookahead = _codePoints[_idx]; + final int lookahead = _string.codeUnitAt(_idx); SvgPathSegType command = AsciiConstants.mapLetterToSegmentType(lookahead); if (_previousCommand == SvgPathSegType.unknown) { // First command has to be a moveto. From 787fa6ca4c42c175c468899b2c202dde4dbb7858 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 5 May 2021 00:42:40 -0700 Subject: [PATCH 13/28] versioning bump --- third_party/packages/path_parsing/CHANGELOG.md | 4 ++++ third_party/packages/path_parsing/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index e606ce6bf9c..e39228ba69a 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 0.2.1 + +- Performance improvements to parsing. + ## 0.2.0 - Stable nullsafe release diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 79c4d1ffd9b..6df3e472e49 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,5 +1,5 @@ name: path_parsing -version: 0.2.0 +version: 0.2.1 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. homepage: https://github.com/dnfield/dart_path_parsing From 94c7958f30b6ec9d9ff697f5c2e035efc62884e3 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Dec 2021 10:14:41 -0800 Subject: [PATCH 14/28] 1.0.0 --- third_party/packages/path_parsing/CHANGELOG.md | 4 ++++ third_party/packages/path_parsing/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index e39228ba69a..8934f8ef3c0 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 1.0.0 + +- Stable release. + ## 0.2.1 - Performance improvements to parsing. diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 6df3e472e49..51034aea5bd 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,5 +1,5 @@ name: path_parsing -version: 0.2.1 +version: 1.0.0 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. homepage: https://github.com/dnfield/dart_path_parsing From 74a10e99332e4bff0e4fdc14c3710e0b171b575f Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 3 Aug 2022 17:31:01 -0700 Subject: [PATCH 15/28] Use radians when rotating matrix (#9) * Use radians when rotating matrix * less precision in tests --- .../packages/path_parsing/CHANGELOG.md | 5 ++ .../path_parsing/lib/src/path_parsing.dart | 52 +++++++++---------- .../packages/path_parsing/pubspec.yaml | 2 +- .../test/parse_path_deep_test.dart | 27 +++++++--- 4 files changed, 52 insertions(+), 34 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 8934f8ef3c0..5b6907a02af 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 1.0.1 + +- Fix [bug in arc decomposition](https://github.com/dnfield/flutter_svg/issues/742). +- Minor code cleanup for analysis warnings. + ## 1.0.0 - Stable release. diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 4dba1d6a5c7..768f00b15a2 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -13,7 +13,7 @@ import 'dart:math' as math show sqrt, max, pi, tan, sin, cos, pow, atan2; import 'package:meta/meta.dart'; -import 'package:vector_math/vector_math.dart' show Matrix4; +import 'package:vector_math/vector_math.dart' show Matrix4, radians; import './path_segment_type.dart'; @@ -178,10 +178,9 @@ class SvgPathStringSource { } bool _isValidRange(double x) => - -double.maxFinite <= x && x <= double.maxFinite; + -double.maxFinite <= x && x <= double.maxFinite; - bool _isValidExponent(double x) => - -37 <= x && x <= 38; + bool _isValidExponent(double x) => -37 <= x && x <= 38; /// Reads a code unit and advances the index. /// @@ -209,8 +208,8 @@ class SvgPathStringSource { c = _readCodeUnit(); } - if ((c < AsciiConstants.number0 || c > AsciiConstants.number9) - && c != AsciiConstants.period) { + if ((c < AsciiConstants.number0 || c > AsciiConstants.number9) && + c != AsciiConstants.period) { throw StateError('First character of a number must be one of [0-9+-.].'); } @@ -232,8 +231,7 @@ class SvgPathStringSource { c = _readCodeUnit(); // There must be a least one digit following the . - if (c < AsciiConstants.number0 || - c > AsciiConstants.number9) + if (c < AsciiConstants.number0 || c > AsciiConstants.number9) throw StateError('There must be at least one digit following the .'); double frac = 1.0; @@ -264,8 +262,7 @@ class SvgPathStringSource { } // There must be an exponent - if (c < AsciiConstants.number0 || - c > AsciiConstants.number9) + if (c < AsciiConstants.number0 || c > AsciiConstants.number9) throw StateError('Missing exponent'); double exponent = 0.0; @@ -408,20 +405,18 @@ class SvgPathStringSource { } } -class OffsetHelper { - static _PathOffset reflectedPoint( - _PathOffset reflectedIn, _PathOffset pointToReflect) { - return _PathOffset(2 * reflectedIn.dx - pointToReflect.dx, - 2 * reflectedIn.dy - pointToReflect.dy); - } +_PathOffset reflectedPoint( + _PathOffset reflectedIn, _PathOffset pointToReflect) { + return _PathOffset(2 * reflectedIn.dx - pointToReflect.dx, + 2 * reflectedIn.dy - pointToReflect.dy); +} - static const double _kOneOverThree = 1.0 / 3.0; +const double _kOneOverThree = 1.0 / 3.0; - /// Blend the points with a ratio (1/3):(2/3). - static _PathOffset blendPoints(_PathOffset p1, _PathOffset p2) { - return _PathOffset((p1.dx + 2 * p2.dx) * _kOneOverThree, - (p1.dy + 2 * p2.dy) * _kOneOverThree); - } +/// Blend the points with a ratio (1/3):(2/3). +_PathOffset blendPoints(_PathOffset p1, _PathOffset p2) { + return _PathOffset((p1.dx + 2 * p2.dx) * _kOneOverThree, + (p1.dy + 2 * p2.dy) * _kOneOverThree); } bool isCubicCommand(SvgPathSegType command) { @@ -448,7 +443,10 @@ class PathSegmentData { _PathOffset get arcRadii => point1; + /// Angle in degrees. double get arcAngle => point2.dx; + + /// In degrees. set arcAngle(double angle) => point2 = _PathOffset(angle, point2.dy); double get r1 => arcRadii.dx; @@ -553,7 +551,7 @@ class SvgPathNormalizer { if (!isCubicCommand(_lastCommand)) { normSeg.point1 = _currentPoint; } else { - normSeg.point1 = OffsetHelper.reflectedPoint( + normSeg.point1 = reflectedPoint( _currentPoint, _controlPoint, ); @@ -578,7 +576,7 @@ class SvgPathNormalizer { if (!isQuadraticCommand(_lastCommand)) { normSeg.point1 = _currentPoint; } else { - normSeg.point1 = OffsetHelper.reflectedPoint( + normSeg.point1 = reflectedPoint( _currentPoint, _controlPoint, ); @@ -589,8 +587,8 @@ class SvgPathNormalizer { case SvgPathSegType.quadToAbs: // Save the unmodified control point. _controlPoint = normSeg.point1; - normSeg.point1 = OffsetHelper.blendPoints(_currentPoint, _controlPoint); - normSeg.point2 = OffsetHelper.blendPoints( + normSeg.point1 = blendPoints(_currentPoint, _controlPoint); + normSeg.point2 = blendPoints( normSeg.targetPoint, _controlPoint, ); @@ -655,7 +653,7 @@ class SvgPathNormalizer { return false; } - final double angle = arcSegment.arcAngle; + final double angle = radians(arcSegment.arcAngle); final _PathOffset midPointDistance = (currentPoint - arcSegment.targetPoint) * 0.5; diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 51034aea5bd..a70652793c4 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,5 +1,5 @@ name: path_parsing -version: 1.0.0 +version: 1.0.1 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. homepage: https://github.com/dnfield/dart_path_parsing diff --git a/third_party/packages/path_parsing/test/parse_path_deep_test.dart b/third_party/packages/path_parsing/test/parse_path_deep_test.dart index e73391bc9e8..8839f068f3e 100644 --- a/third_party/packages/path_parsing/test/parse_path_deep_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_deep_test.dart @@ -21,17 +21,20 @@ class DeepTestPathProxy extends PathProxy { double x3, double y3, ) { - actualCommands.add('cubicTo($x1, $y1, $x2, $y2, $x3, $y3)'); + actualCommands.add( + 'cubicTo(${x1.toStringAsFixed(4)}, ${y1.toStringAsFixed(4)}, ${x2.toStringAsFixed(4)}, ${y2.toStringAsFixed(4)}, ${x3.toStringAsFixed(4)}, ${y3.toStringAsFixed(4)})'); } @override void lineTo(double x, double y) { - actualCommands.add('lineTo($x, $y)'); + actualCommands + .add('lineTo(${x.toStringAsFixed(4)}, ${y.toStringAsFixed(4)})'); } @override void moveTo(double x, double y) { - actualCommands.add('moveTo($x, $y)'); + actualCommands + .add('moveTo(${x.toStringAsFixed(4)}, ${y.toStringAsFixed(4)})'); } void validate() { @@ -48,9 +51,21 @@ void main() { test('Deep path validation', () { assertValidPath('M20,30 Q40,5 60,30 T100,30', [ - 'moveTo(20.0, 30.0)', - 'cubicTo(33.33333333333333, 13.333333333333332, 46.666666666666664, 13.333333333333332, 60.0, 30.0)', - 'cubicTo(73.33333333333333, 46.666666666666664, 86.66666666666666, 46.666666666666664, 100.0, 30.0)', + 'moveTo(20.0000, 30.0000)', + 'cubicTo(33.3333, 13.3333, 46.6667, 13.3333, 60.0000, 30.0000)', + 'cubicTo(73.3333, 46.6667, 86.6667, 46.6667, 100.0000, 30.0000)' + ]); + + assertValidPath( + 'M5.5 5.5a.5 1.5 30 1 1-.866-.5.5 1.5 30 1 1 .866.5z', [ + 'moveTo(5.5000, 5.5000)', + 'cubicTo(5.2319, 5.9667, 4.9001, 6.3513, 4.6307, 6.5077)', + 'cubicTo(4.3612, 6.6640, 4.1953, 6.5683, 4.1960, 6.2567)', + 'cubicTo(4.1967, 5.9451, 4.3638, 5.4655, 4.6340, 5.0000)', + 'cubicTo(4.9021, 4.5333, 5.2339, 4.1487, 5.5033, 3.9923)', + 'cubicTo(5.7728, 3.8360, 5.9387, 3.9317, 5.9380, 4.2433)', + 'cubicTo(5.9373, 4.5549, 5.7702, 5.0345, 5.5000, 5.5000)', + 'close()' ]); }); } From ebafccec209fb096fc6f829fd4036228f58aed46 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Wed, 5 Oct 2022 16:52:21 -0700 Subject: [PATCH 16/28] inlined the reading of code units (#10) --- third_party/packages/path_parsing/lib/src/path_parsing.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 768f00b15a2..2df3cc343be 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -185,6 +185,7 @@ class SvgPathStringSource { /// Reads a code unit and advances the index. /// /// Returns -1 if at end of string. + @pragma('vm:prefer-inline') int _readCodeUnit() { if (_idx >= _length) { return -1; From 6fd4a9eb98962625fa48787c004f4528d5fcfc94 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:21:10 -0400 Subject: [PATCH 17/28] Remove Cirrus config --- third_party/packages/path_parsing/.cirrus.yml | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 third_party/packages/path_parsing/.cirrus.yml diff --git a/third_party/packages/path_parsing/.cirrus.yml b/third_party/packages/path_parsing/.cirrus.yml deleted file mode 100644 index c9ee69af152..00000000000 --- a/third_party/packages/path_parsing/.cirrus.yml +++ /dev/null @@ -1,20 +0,0 @@ -env: - CI_NAME: "CirrusCI" - CI_BUILD_NUMBER: $CIRRUS_TASK_ID - CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID" - CI_BRANCH: $CIRRUS_BRANCH - CI_PULL_REQUEST: $CIRRUS_PR - COVERALLS_REPO_TOKEN: ENCRYPTED[818fc7b63ab15e18ff5f9813b9983dba79ffb6a9a21861f7797096c0522e0b7ad07fa0b994f87d8187da8f8f9ce3b8ef] - -test_task: - container: - matrix: - - image: cirrusci/flutter:dev - - image: cirrusci/flutter:stable - pub_cache: - folder: ~/.pub-cache - analyze_script: flutter analyze . - test_script: flutter test --coverage - coveralls_script: | - dart pub global activate coveralls - dart pub global run coveralls coverage/lcov.info From fb82a4bd12dd85edbffafdfc57d2fb37618627fc Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:23:06 -0400 Subject: [PATCH 18/28] CHANGELOG format --- third_party/packages/path_parsing/CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 5b6907a02af..cc8f7f3af6c 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,5 +1,3 @@ -# CHANGELOG - ## 1.0.1 - Fix [bug in arc decomposition](https://github.com/dnfield/flutter_svg/issues/742). From ca49442260c0e4458981bd9605135604bec6bf2b Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:46:14 -0400 Subject: [PATCH 19/28] Remove analysis options, update code accordingly --- .../path_parsing/analysis_options.yaml | 146 ------------------ .../packages/path_parsing/example/main.dart | 2 + .../path_parsing/example/pubspec.lock | 14 +- .../path_parsing/lib/src/path_parsing.dart | 48 +++--- .../lib/src/path_segment_type.dart | 3 +- .../packages/path_parsing/pubspec.lock | 146 ++++++++++++------ .../packages/path_parsing/pubspec.yaml | 4 +- .../path_parsing/test/parse_path_test.dart | 30 ++-- 8 files changed, 149 insertions(+), 244 deletions(-) delete mode 100644 third_party/packages/path_parsing/analysis_options.yaml diff --git a/third_party/packages/path_parsing/analysis_options.yaml b/third_party/packages/path_parsing/analysis_options.yaml deleted file mode 100644 index d23cbd0c131..00000000000 --- a/third_party/packages/path_parsing/analysis_options.yaml +++ /dev/null @@ -1,146 +0,0 @@ -# Specify analysis options. -# -# Until there are meta linter rules, each desired lint must be explicitly enabled. -# See: https://github.com/dart-lang/linter/issues/288 -# -# For a list of lints, see: http://dart-lang.github.io/linter/lints/ -# See the configuration guide for more -# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer -# -# There are four similar analysis options files in the flutter repos: -# - analysis_options.yaml (this file) -# - packages/flutter/lib/analysis_options_user.yaml -# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml -# - https://github.com/flutter/engine/blob/master/analysis_options.yaml -# -# This file contains the analysis options used by Flutter tools, such as IntelliJ, -# Android Studio, and the `flutter analyze` command. -# -# The flutter/plugins repo contains a copy of this file, which should be kept -# in sync with this file. - -analyzer: - strong-mode: - implicit-dynamic: false - errors: - # treat missing returns as a warning (not a hint) - missing_return: warning - # allow having TODOs in the code - todo: ignore - exclude: - # for Travis - don't try to analyze the flutter repo - - 'flutter/**' - - -linter: - rules: - # these rules are documented on and in the same order as - # the Dart Lint rules page to make maintenance easier - # https://github.com/dart-lang/linter/blob/master/example/all.yaml - - always_declare_return_types - - always_put_control_body_on_new_line - # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 - - always_require_non_null_named_parameters - - always_specify_types - - annotate_overrides - # - avoid_annotating_with_dynamic # conflicts with always_specify_types - # - avoid_bool_literals_in_conditional_expressions # not yet tested - # - avoid_catches_without_on_clauses # we do this commonly - # - avoid_catching_errors # we do this commonly - - avoid_classes_with_only_static_members - - avoid_empty_else - - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - # - avoid_positional_boolean_parameters # not yet tested - # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - # - avoid_returning_null # we do this commonly - # - avoid_returning_this # https://github.com/dart-lang/linter/issues/842 - # - avoid_setters_without_getters # not yet tested - # - avoid_single_cascade_in_expression_statements # not yet tested - - avoid_slow_async_io - # - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files - # - avoid_types_on_closure_parameters # conflicts with always_specify_types - # - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847 - - await_only_futures - - camel_case_types - - cancel_subscriptions - # - cascade_invocations # not yet tested - # - close_sinks # https://github.com/flutter/flutter/issues/5789 - # - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153 - # - constant_identifier_names # https://github.com/dart-lang/linter/issues/204 - - control_flow_in_finally - - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - hash_and_equals - - implementation_imports - # - invariant_booleans # https://github.com/flutter/flutter/issues/5790 - - iterable_contains_unrelated_type - # - join_return_with_assignment # not yet tested - - library_names - - library_prefixes - - list_remove_unrelated_type - # - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791 - - no_adjacent_strings_in_list - - no_duplicate_case_values - - non_constant_identifier_names - # - omit_local_variable_types # opposite of always_specify_types - # - one_member_abstracts # too many false positives - # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - # - parameter_assignments # we do this commonly - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - # - prefer_constructors_over_static_methods # not yet tested - - prefer_contains - # - prefer_equal_for_default_values # not yet tested - # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods - - prefer_final_fields - - prefer_final_locals - - prefer_foreach - # - prefer_function_declarations_over_variables # not yet tested - - prefer_initializing_formals - # - prefer_interpolation_to_compose_strings # not yet tested - - prefer_is_empty - - prefer_is_not_empty - - prefer_single_quotes - - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - - sort_constructors_first - - sort_unnamed_constructors_first - - test_types_in_equals - - throw_in_finally - # - type_annotate_public_apis # subset of always_specify_types - - type_init_formals - # - unawaited_futures # https://github.com/flutter/flutter/issues/5793 - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - # - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498 - - unnecessary_null_aware_assignments - - unnecessary_null_in_if_null_operators - - unnecessary_overrides - - unnecessary_parenthesis - # - unnecessary_statements # not yet tested - - unnecessary_this - - unrelated_type_equality_checks - - use_rethrow_when_possible - # - use_setters_to_change_properties # not yet tested - # - use_string_buffers # https://github.com/dart-lang/linter/pull/664 - # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - - valid_regexps - - unnecessary_new \ No newline at end of file diff --git a/third_party/packages/path_parsing/example/main.dart b/third_party/packages/path_parsing/example/main.dart index c5e03a68c75..1d378235a46 100644 --- a/third_party/packages/path_parsing/example/main.dart +++ b/third_party/packages/path_parsing/example/main.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_print + import 'package:path_parsing/path_parsing.dart'; /// A [PathProxy] that dumps Flutter `Path` commands to the console. diff --git a/third_party/packages/path_parsing/example/pubspec.lock b/third_party/packages/path_parsing/example/pubspec.lock index f5dd70baa2c..7353bfef9c2 100644 --- a/third_party/packages/path_parsing/example/pubspec.lock +++ b/third_party/packages/path_parsing/example/pubspec.lock @@ -5,22 +5,24 @@ packages: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" source: hosted - version: "1.3.0-nullsafety.6" + version: "1.16.0" path_parsing: dependency: "direct main" description: path: ".." relative: true source: path - version: "0.2.0-nullsafety.0" + version: "1.0.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.0-nullsafety.5" + version: "2.1.4" sdks: - dart: ">=2.12.0-0 <3.0.0" + dart: ">=2.14.0 <4.0.0" diff --git a/third_party/packages/path_parsing/lib/src/path_parsing.dart b/third_party/packages/path_parsing/lib/src/path_parsing.dart index 2df3cc343be..1a750a861c6 100644 --- a/third_party/packages/path_parsing/lib/src/path_parsing.dart +++ b/third_party/packages/path_parsing/lib/src/path_parsing.dart @@ -10,7 +10,13 @@ // * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/html/parser/html_parser_idioms.h (IsHTMLSpace) // * https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser_test.cc -import 'dart:math' as math show sqrt, max, pi, tan, sin, cos, pow, atan2; +// TODO(stuartmorgan): Remove public_member_api_docs, adding documentation for +// all public members. +// TODO(stuartmorgan): Remove library_private_types_in_public_api and do a +// breaking change to not use _PathOffset in public APIs. +// ignore_for_file: public_member_api_docs, library_private_types_in_public_api + +import 'dart:math' as math show atan2, cos, max, pi, pow, sin, sqrt, tan; import 'package:meta/meta.dart'; import 'package:vector_math/vector_math.dart' show Matrix4, radians; @@ -25,7 +31,7 @@ void writeSvgPathDataToPath(String? svg, PathProxy path) { final SvgPathStringSource parser = SvgPathStringSource(svg); final SvgPathNormalizer normalizer = SvgPathNormalizer(); - for (PathSegmentData seg in parser.parseSegments()) { + for (final PathSegmentData seg in parser.parseSegments()) { normalizer.emitSegment(seg, path); } } @@ -165,8 +171,10 @@ class SvgPathStringSource { // could be the start of an implicit command. The 'close' command does not // have any parameters though and hence can't have an implicit // 'continuation'. - if (!_isNumberStart(lookahead) || _previousCommand == SvgPathSegType.close) + if (!_isNumberStart(lookahead) || + _previousCommand == SvgPathSegType.close) { return nextCommand; + } // Implicit continuations of moveto command translate to linetos. if (_previousCommand == SvgPathSegType.moveToAbs) { return SvgPathSegType.lineToAbs; @@ -232,8 +240,9 @@ class SvgPathStringSource { c = _readCodeUnit(); // There must be a least one digit following the . - if (c < AsciiConstants.number0 || c > AsciiConstants.number9) + if (c < AsciiConstants.number0 || c > AsciiConstants.number9) { throw StateError('There must be at least one digit following the .'); + } double frac = 1.0; while (AsciiConstants.number0 <= c && c <= AsciiConstants.number9) { @@ -263,8 +272,9 @@ class SvgPathStringSource { } // There must be an exponent - if (c < AsciiConstants.number0 || c > AsciiConstants.number9) + if (c < AsciiConstants.number0 || c > AsciiConstants.number9) { throw StateError('Missing exponent'); + } double exponent = 0.0; while (c >= AsciiConstants.number0 && c <= AsciiConstants.number9) { @@ -310,12 +320,13 @@ class SvgPathStringSource { final int flagChar = _string.codeUnitAt(_idx++); _skipOptionalSvgSpacesOrDelimiter(); - if (flagChar == AsciiConstants.number0) + if (flagChar == AsciiConstants.number0) { return false; - else if (flagChar == AsciiConstants.number1) + } else if (flagChar == AsciiConstants.number1) { return true; - else + } else { throw StateError('Invalid flag value'); + } } bool get hasMoreData => _idx < _length; @@ -371,25 +382,20 @@ class SvgPathStringSource { quad_smooth: case SvgPathSegType.smoothQuadToAbs: segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); - break; case SvgPathSegType.lineToHorizontalRel: case SvgPathSegType.lineToHorizontalAbs: segment.targetPoint = _PathOffset(_parseNumber(), segment.targetPoint.dy); - break; case SvgPathSegType.lineToVerticalRel: case SvgPathSegType.lineToVerticalAbs: segment.targetPoint = _PathOffset(segment.targetPoint.dx, _parseNumber()); - break; case SvgPathSegType.close: _skipOptionalSvgSpaces(); - break; case SvgPathSegType.quadToRel: case SvgPathSegType.quadToAbs: segment.point1 = _PathOffset(_parseNumber(), _parseNumber()); segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); - break; case SvgPathSegType.arcToRel: case SvgPathSegType.arcToAbs: segment.point1 = _PathOffset(_parseNumber(), _parseNumber()); @@ -397,7 +403,6 @@ class SvgPathStringSource { segment.arcLarge = _parseArcFlag(); segment.arcSweep = _parseArcFlag(); segment.targetPoint = _PathOffset(_parseNumber(), _parseNumber()); - break; case SvgPathSegType.unknown: throw StateError('Unknown segment command'); } @@ -492,7 +497,6 @@ class SvgPathNormalizer { case SvgPathSegType.quadToRel: normSeg.point1 += _currentPoint; normSeg.targetPoint += _currentPoint; - break; case SvgPathSegType.cubicToRel: normSeg.point1 += _currentPoint; continue smooth_rel; @@ -508,19 +512,17 @@ class SvgPathNormalizer { arc_rel: case SvgPathSegType.arcToRel: normSeg.targetPoint += _currentPoint; - break; case SvgPathSegType.lineToHorizontalAbs: normSeg.targetPoint = _PathOffset(normSeg.targetPoint.dx, _currentPoint.dy); - break; case SvgPathSegType.lineToVerticalAbs: normSeg.targetPoint = _PathOffset(_currentPoint.dx, normSeg.targetPoint.dy); - break; case SvgPathSegType.close: // Reset m_currentPoint for the next path. normSeg.targetPoint = _subPathPoint; - break; + // This switch is intentionally non-exhaustive. + // ignore: no_default_cases default: break; } @@ -533,7 +535,6 @@ class SvgPathNormalizer { _subPathPoint = normSeg.targetPoint; // normSeg.command = SvgPathSegType.moveToAbs; path.moveTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); - break; case SvgPathSegType.lineToRel: case SvgPathSegType.lineToAbs: case SvgPathSegType.lineToHorizontalRel: @@ -542,11 +543,9 @@ class SvgPathNormalizer { case SvgPathSegType.lineToVerticalAbs: // normSeg.command = SvgPathSegType.lineToAbs; path.lineTo(normSeg.targetPoint.dx, normSeg.targetPoint.dy); - break; case SvgPathSegType.close: // normSeg.command = SvgPathSegType.close; path.close(); - break; case SvgPathSegType.smoothCubicToRel: case SvgPathSegType.smoothCubicToAbs: if (!isCubicCommand(_lastCommand)) { @@ -571,7 +570,6 @@ class SvgPathNormalizer { normSeg.targetPoint.dx, normSeg.targetPoint.dy, ); - break; case SvgPathSegType.smoothQuadToRel: case SvgPathSegType.smoothQuadToAbs: if (!isQuadraticCommand(_lastCommand)) { @@ -602,7 +600,6 @@ class SvgPathNormalizer { normSeg.targetPoint.dx, normSeg.targetPoint.dy, ); - break; case SvgPathSegType.arcToRel: case SvgPathSegType.arcToAbs: if (!_decomposeArcToCubic(_currentPoint, normSeg, path)) { @@ -615,7 +612,8 @@ class SvgPathNormalizer { // // emit. // // normSeg.command = SvgPathSegType.arcToAbs; } - break; + // This switch is intentionally non-exhaustive. + // ignore: no_default_cases default: throw StateError('Invalid command type in path'); } diff --git a/third_party/packages/path_parsing/lib/src/path_segment_type.dart b/third_party/packages/path_parsing/lib/src/path_segment_type.dart index b104f5635ec..0c2c097cb6d 100644 --- a/third_party/packages/path_parsing/lib/src/path_segment_type.dart +++ b/third_party/packages/path_parsing/lib/src/path_segment_type.dart @@ -72,6 +72,7 @@ enum SvgPathSegType { class AsciiConstants { const AsciiConstants._(); + /// Returns the segment type corresponding to the letter constant [lookahead]. static SvgPathSegType mapLetterToSegmentType(int lookahead) { return AsciiConstants.letterToSegmentType[lookahead] ?? SvgPathSegType.unknown; @@ -79,7 +80,7 @@ class AsciiConstants { /// Map to go from ASCII constant to [SvgPathSegType] static const Map letterToSegmentType = - const { + { upperZ: SvgPathSegType.close, lowerZ: SvgPathSegType.close, upperM: SvgPathSegType.moveToAbs, diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock index c28f3ab60ef..37116263e14 100644 --- a/third_party/packages/path_parsing/pubspec.lock +++ b/third_party/packages/path_parsing/pubspec.lock @@ -5,337 +5,385 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "21bc4be2d357e2a995bb290676a1abc440b1524dfe4e822a60bc26cf11beecf9" + url: "https://pub.dev" source: hosted version: "19.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "6baf4ef66a70521a94d3ccde61968969b67fa2232f989590c078f8a0789883ce" + url: "https://pub.dev" source: hosted version: "1.3.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "37a4264b0b7fb930e94c0c47558f3b6c4f4e9cb7e655a3ea373131d79b2dc0cc" + url: "https://pub.dev" source: hosted version: "2.0.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "6eda8392a48ae1de7ea438c91a4ba3e77205f043e7013102a424863aa6db368f" + url: "https://pub.dev" source: hosted version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "5bbf32bc9e518d41ec49718e2931cd4527292c9b0c6d2dffcf7fe6b9a8a8cf72" + url: "https://pub.dev" source: hosted version: "2.1.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: "8e36feea6de5ea69f2199f29cf42a450a855738c498b57c0b980e2d3cca9c362" + url: "https://pub.dev" source: hosted version: "1.2.0" cli_util: dependency: transitive description: name: cli_util - url: "https://pub.dartlang.org" + sha256: cf1c02840bbbcf8fcd13feb5933c62d643cc58ddf4f6088707cf48d1892cbc5d + url: "https://pub.dev" source: hosted version: "0.3.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "6d4193120997ecfd09acf0e313f13dc122b119e5eca87ef57a7d065ec9183762" + url: "https://pub.dev" source: hosted version: "1.15.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: df567b950053d83b4dba3e8c5799c411895d146f82b2147114b666a4fd9a80dd + url: "https://pub.dev" source: hosted version: "3.0.0" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "2890d8a09829de2cc3ead1407960549e4eb3c4e48c8fb837bfa5c68398496489" + url: "https://pub.dev" source: hosted version: "1.0.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: cf75650c66c0316274e21d7c43d3dea246273af5955bd94e8184837cd577575c + url: "https://pub.dev" source: hosted version: "3.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "9fd2163d866769f60f4df8ac1dc59f52498d810c356fe78022e383dd3c57c0e1" + url: "https://pub.dev" source: hosted version: "6.1.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: dda85ce2aefce16f7e75586acbcb1e8320bf176f69fd94082e31945d6de67f3e + url: "https://pub.dev" source: hosted version: "2.0.1" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: ac10cae1b9a06fb638a92a72b00570bac856f524f7ee0d9a13eaed4960c7fd43 + url: "https://pub.dev" source: hosted version: "3.0.0" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185 + url: "https://pub.dev" source: hosted version: "4.0.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "15a5436d2a02dc60e6dc2fb5d7dfaac08b7b137cff3d4bf3158d38ecab656b69" + url: "https://pub.dev" source: hosted version: "1.0.0" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: d9bdfd70d828eeb352390f81b18d6a354ef2044aa28ef25682079797fa7cd174 + url: "https://pub.dev" source: hosted version: "0.6.3" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "0520a4826042a8a5d09ddd4755623a50d37ee536d79a70452aff8c8ad7bb6c27" + url: "https://pub.dev" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "38c7be344ac5057e10161a5ecb00c9d9d67ed2f150001278601dd27d9fe64206" + url: "https://pub.dev" source: hosted version: "0.12.10" meta: dependency: "direct main" description: name: meta - url: "https://pub.dartlang.org" + sha256: "98a7492d10d7049ea129fd4e50f7cdd2d5008522b1dfa1148bbbc542b9dd21f7" + url: "https://pub.dev" source: hosted version: "1.3.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: a7a98ea7f366e2cc9d2b20873815aebec5e2bc124fe0da9d3f7f59b0625ea180 + url: "https://pub.dev" source: hosted version: "1.0.0" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: c133f761a6a790d0b000efa4f74eae9700bb6e9e9f5e996f0e8d6fe92703ced6 + url: "https://pub.dev" source: hosted version: "2.0.0" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "20e7154d701fedaeb219dad732815ecb66677667871127998a9a6581c2aba4ba" + url: "https://pub.dev" source: hosted version: "2.0.0" path: dependency: "direct dev" description: name: path - url: "https://pub.dartlang.org" + sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb" + url: "https://pub.dev" source: hosted version: "1.8.0" pedantic: dependency: transitive description: name: pedantic - url: "https://pub.dartlang.org" + sha256: "8f6460c77a98ad2807cd3b98c67096db4286f56166852d0ce5951bb600a63594" + url: "https://pub.dev" source: hosted version: "1.11.0" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "05955e3de2683e1746222efd14b775df7131139e07695dc8e24650f6b4204504" + url: "https://pub.dev" source: hosted version: "1.5.0" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "59ed538734419e81f7fc18c98249ae72c3c7188bdd9dceff2840585227f79843" + url: "https://pub.dev" source: hosted version: "2.0.0" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c2f658d28ec86857657dec3579e2db4dc5a6c477b6aecde870e77f0682258901 + url: "https://pub.dev" source: hosted version: "1.1.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: e0b44ebddec91e70a713e13adf93c1b2100821303b86a18e1ef1d082bd8bd9b8 + url: "https://pub.dev" source: hosted version: "3.0.0" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: "8584c0aa0f5756a61519b1a2fc2cd22ddbc518e9396bd33ebf06b9836bb23d13" + url: "https://pub.dev" source: hosted version: "1.0.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: fd84910bf7d58db109082edf7326b75322b8f186162028482f53dc892f00332d + url: "https://pub.dev" source: hosted version: "1.0.1" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "8c463326277f68a628abab20580047b419c2ff66756fd0affd451f73f9508c11" + url: "https://pub.dev" source: hosted version: "2.1.0" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "52de2200bb098de739794c82d09c41ac27b2e42fd7e23cce7b9c74bf653c7296" + url: "https://pub.dev" source: hosted version: "0.10.10" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: d5f89a9e52b36240a80282b3dc0667dd36e53459717bb17b8fb102d30496606a + url: "https://pub.dev" source: hosted version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: f8d9f247e2f9f90e32d1495ff32dac7e4ae34ffa7194c5ff8fcc0fd0e52df774 + url: "https://pub.dev" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: db47e4797198ee601990820437179bb90219f918962318d494ada2b4b11e6f6d + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: dd11571b8a03f7cadcf91ec26a77e02bfbd6bbba2a512924d3116646b4198fc4 + url: "https://pub.dev" source: hosted version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a88162591b02c1f3a3db3af8ce1ea2b374bd75a7bb8d5e353bcfbdc79d719830 + url: "https://pub.dev" source: hosted version: "1.2.0" test: dependency: "direct dev" description: name: test - url: "https://pub.dartlang.org" + sha256: "51bed717b867dd91d75b804c8abbfb30cf904d30c00bea3d5467f3c3c7d4e064" + url: "https://pub.dev" source: hosted version: "1.16.8" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "9ddd24ec429417cfffd744115508a95f0ee956ec02a2d972dd7fbfbfe047cf45" + url: "https://pub.dev" source: hosted version: "0.3.0" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "9567514cac32e25165c78bd2c98092b3f7fd5a1555114b4f08d83830d6645e33" + url: "https://pub.dev" source: hosted version: "0.3.19" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" + url: "https://pub.dev" source: hosted version: "1.3.0" vector_math: dependency: "direct main" description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "15cdf04f64b23c2ff6b999c193cbb0c928698dc602ed73075b9562527fcb5bb5" + url: "https://pub.dev" source: hosted version: "2.1.0" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: "422eda09e2a50eb27fe9eca2c897d624cea7fa432a8442e1ea1a10d50a4321ab" + url: "https://pub.dev" source: hosted version: "6.2.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "68173f2fa67d241323a4123be7ed4e43424c54befa5505d71c8ad4b7baf8f71d" + url: "https://pub.dev" source: hosted version: "1.0.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: "500e6014efebd305a30ebf1c6006d13faa82dcd85c7a2a7793679a64ed69ec48" + url: "https://pub.dev" source: hosted version: "2.0.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "5adb6ab8ed14e22bb907aae7338f0c206ea21e7a27004e97664b16c120306f00" + url: "https://pub.dev" source: hosted version: "1.0.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" + url: "https://pub.dev" source: hosted version: "3.1.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=3.3.0 <4.0.0" diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index a70652793c4..4b30a8c243c 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -5,12 +5,12 @@ description: > homepage: https://github.com/dnfield/dart_path_parsing dependencies: - vector_math: ^2.1.0 meta: ^1.3.0 + vector_math: ^2.1.0 dev_dependencies: path: ^1.8.0 test: ^1.16.0 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ^3.3.0 diff --git a/third_party/packages/path_parsing/test/parse_path_test.dart b/third_party/packages/path_parsing/test/parse_path_test.dart index 72c4e370efa..0f8a5117e2a 100644 --- a/third_party/packages/path_parsing/test/parse_path_test.dart +++ b/third_party/packages/path_parsing/test/parse_path_test.dart @@ -82,8 +82,8 @@ void main() { assertValidPath('M100,200 a3,4,5,016,7'); assertValidPath('M100,200 a3,4,5,106,7'); assertValidPath('M100,200 a3,4,5,116,7'); - assertValidPath( - '''M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 + assertValidPath(''' +M19.0281,19.40466 20.7195,19.40466 20.7195,15.71439 24.11486,15.71439 24.11486,14.36762 20.7195,14.36762 20.7195,11.68641 24.74134,11.68641 24.74134,10.34618 19.0281,10.34618 z'''); assertValidPath( @@ -124,27 +124,27 @@ void main() { assertValidPath( 'M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 ' '-4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 ' - '0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803' - 'C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 ' + '0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 ' + '11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 ' '4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 ' '21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 ' '17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 ' - '-0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976' - 'C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 ' + '-0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 ' + '22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 ' '17.1277 27.2802 8.87841 22.1595 3.80852Z'); assertValidPath( 'm18 11.8a.41.41 0 0 1 .24.08l.59.43h.05.72a.4.4 0 0 1 .39.28l.22.69a.08.08 0 ' '0 0 0 0l.58.43a.41.41 0 0 1 .15.45l-.22.68a.09.09 0 0 0 0 .07l.22.68a.4.4 0 0 1 ' '-.15.46l-.58.42a.1.1 0 0 0 0 0l-.22.68a.41.41 0 0 1 -.38.29h-.79l-.58.43a.41.41 0 ' - '0 1 -.24.08.46.46 0 0 1 -.24-.08l-.58-.43h-.06-.72a.41.41 0 0 1 -.39-.28l-.22-.68' - 'a.1.1 0 0 0 0 0l-.58-.43a.42.42 0 0 1 -.15-.46l.23-.67v-.02l-.29-.68a.43.43 0 0 1 ' + '0 1 -.24.08.46.46 0 0 1 -.24-.08l-.58-.43h-.06-.72a.41.41 0 0 1 -.39-.28l-.22-.68a.1.1 ' + '0 0 0 0 0l-.58-.43a.42.42 0 0 1 -.15-.46l.23-.67v-.02l-.29-.68a.43.43 0 0 1 ' '.15-.46l.58-.42a.1.1 0 0 0 0-.05l.27-.69a.42.42 0 0 1 .39-.28h.78l.58-.43a.43.43 0 ' - '0 1 .25-.09m0-1a1.37 1.37 0 0 0 -.83.27l-.34.25h-.43a1.42 1.42 0 0 0 -1.34 1l-.13.4' - '-.35.25a1.42 1.42 0 0 0 -.51 1.58l.13.4-.13.4a1.39 1.39 0 0 0 .52 1.59l.34.25.13.4' - 'a1.41 1.41 0 0 0 1.34 1h.43l.34.26a1.44 1.44 0 0 0 .83.27 1.38 1.38 0 0 0 .83-.28' - 'l.35-.24h.43a1.4 1.4 0 0 0 1.33-1l.13-.4.35-.26a1.39 1.39 0 0 0 .51-1.57l-.13-.4.13-.41' - 'a1.4 1.4 0 0 0 -.51-1.56l-.35-.25-.13-.41a1.4 1.4 0 0 0 -1.34-1h-.42l-.34-.26a1.43 1.43 ' - '0 0 0 -.84-.28z'); + '0 1 .25-.09m0-1a1.37 1.37 0 0 0 -.83.27l-.34.25h-.43a1.42 1.42 0 0 0 -1.34 ' + '1l-.13.4-.35.25a1.42 1.42 0 0 0 -.51 1.58l.13.4-.13.4a1.39 1.39 0 0 0 .52 ' + '1.59l.34.25.13.4a1.41 1.41 0 0 0 1.34 1h.43l.34.26a1.44 1.44 0 0 0 .83.27 1.38 1.38 0 0 0 ' + '.83-.28l.35-.24h.43a1.4 1.4 0 0 0 1.33-1l.13-.4.35-.26a1.39 1.39 0 0 0 ' + '.51-1.57l-.13-.4.13-.41a1.4 1.4 0 0 0 -.51-1.56l-.35-.25-.13-.41a1.4 1.4 0 0 0 ' + '-1.34-1h-.42l-.34-.26a1.43 1.43 0 0 0 -.84-.28z'); }); test('Malformed Paths', () { @@ -161,7 +161,7 @@ void main() { assertInvalidPath('L1,2'); assertInvalidPath('M'); - assertInvalidPath('M\0'); + assertInvalidPath('M0'); assertInvalidPath('M1,1Z0'); assertInvalidPath('M1,1z0'); From c0a1530ee98b85befa073372b8fc897a6640c5f0 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:48:09 -0400 Subject: [PATCH 20/28] No pubspec lock files checked in, per repo convention --- .../path_parsing/example/pubspec.lock | 28 -- .../packages/path_parsing/pubspec.lock | 389 ------------------ 2 files changed, 417 deletions(-) delete mode 100644 third_party/packages/path_parsing/example/pubspec.lock delete mode 100644 third_party/packages/path_parsing/pubspec.lock diff --git a/third_party/packages/path_parsing/example/pubspec.lock b/third_party/packages/path_parsing/example/pubspec.lock deleted file mode 100644 index 7353bfef9c2..00000000000 --- a/third_party/packages/path_parsing/example/pubspec.lock +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - path_parsing: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "1.0.1" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" -sdks: - dart: ">=2.14.0 <4.0.0" diff --git a/third_party/packages/path_parsing/pubspec.lock b/third_party/packages/path_parsing/pubspec.lock deleted file mode 100644 index 37116263e14..00000000000 --- a/third_party/packages/path_parsing/pubspec.lock +++ /dev/null @@ -1,389 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: "21bc4be2d357e2a995bb290676a1abc440b1524dfe4e822a60bc26cf11beecf9" - url: "https://pub.dev" - source: hosted - version: "19.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "6baf4ef66a70521a94d3ccde61968969b67fa2232f989590c078f8a0789883ce" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - args: - dependency: transitive - description: - name: args - sha256: "37a4264b0b7fb930e94c0c47558f3b6c4f4e9cb7e655a3ea373131d79b2dc0cc" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - async: - dependency: transitive - description: - name: async - sha256: "6eda8392a48ae1de7ea438c91a4ba3e77205f043e7013102a424863aa6db368f" - url: "https://pub.dev" - source: hosted - version: "2.5.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "5bbf32bc9e518d41ec49718e2931cd4527292c9b0c6d2dffcf7fe6b9a8a8cf72" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - charcode: - dependency: transitive - description: - name: charcode - sha256: "8e36feea6de5ea69f2199f29cf42a450a855738c498b57c0b980e2d3cca9c362" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: cf1c02840bbbcf8fcd13feb5933c62d643cc58ddf4f6088707cf48d1892cbc5d - url: "https://pub.dev" - source: hosted - version: "0.3.0" - collection: - dependency: transitive - description: - name: collection - sha256: "6d4193120997ecfd09acf0e313f13dc122b119e5eca87ef57a7d065ec9183762" - url: "https://pub.dev" - source: hosted - version: "1.15.0" - convert: - dependency: transitive - description: - name: convert - sha256: df567b950053d83b4dba3e8c5799c411895d146f82b2147114b666a4fd9a80dd - url: "https://pub.dev" - source: hosted - version: "3.0.0" - coverage: - dependency: transitive - description: - name: coverage - sha256: "2890d8a09829de2cc3ead1407960549e4eb3c4e48c8fb837bfa5c68398496489" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - crypto: - dependency: transitive - description: - name: crypto - sha256: cf75650c66c0316274e21d7c43d3dea246273af5955bd94e8184837cd577575c - url: "https://pub.dev" - source: hosted - version: "3.0.1" - file: - dependency: transitive - description: - name: file - sha256: "9fd2163d866769f60f4df8ac1dc59f52498d810c356fe78022e383dd3c57c0e1" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - glob: - dependency: transitive - description: - name: glob - sha256: dda85ce2aefce16f7e75586acbcb1e8320bf176f69fd94082e31945d6de67f3e - url: "https://pub.dev" - source: hosted - version: "2.0.1" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: ac10cae1b9a06fb638a92a72b00570bac856f524f7ee0d9a13eaed4960c7fd43 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - io: - dependency: transitive - description: - name: io - sha256: "15a5436d2a02dc60e6dc2fb5d7dfaac08b7b137cff3d4bf3158d38ecab656b69" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - js: - dependency: transitive - description: - name: js - sha256: d9bdfd70d828eeb352390f81b18d6a354ef2044aa28ef25682079797fa7cd174 - url: "https://pub.dev" - source: hosted - version: "0.6.3" - logging: - dependency: transitive - description: - name: logging - sha256: "0520a4826042a8a5d09ddd4755623a50d37ee536d79a70452aff8c8ad7bb6c27" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - matcher: - dependency: transitive - description: - name: matcher - sha256: "38c7be344ac5057e10161a5ecb00c9d9d67ed2f150001278601dd27d9fe64206" - url: "https://pub.dev" - source: hosted - version: "0.12.10" - meta: - dependency: "direct main" - description: - name: meta - sha256: "98a7492d10d7049ea129fd4e50f7cdd2d5008522b1dfa1148bbbc542b9dd21f7" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - mime: - dependency: transitive - description: - name: mime - sha256: a7a98ea7f366e2cc9d2b20873815aebec5e2bc124fe0da9d3f7f59b0625ea180 - url: "https://pub.dev" - source: hosted - version: "1.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: c133f761a6a790d0b000efa4f74eae9700bb6e9e9f5e996f0e8d6fe92703ced6 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: "20e7154d701fedaeb219dad732815ecb66677667871127998a9a6581c2aba4ba" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - path: - dependency: "direct dev" - description: - name: path - sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb" - url: "https://pub.dev" - source: hosted - version: "1.8.0" - pedantic: - dependency: transitive - description: - name: pedantic - sha256: "8f6460c77a98ad2807cd3b98c67096db4286f56166852d0ce5951bb600a63594" - url: "https://pub.dev" - source: hosted - version: "1.11.0" - pool: - dependency: transitive - description: - name: pool - sha256: "05955e3de2683e1746222efd14b775df7131139e07695dc8e24650f6b4204504" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "59ed538734419e81f7fc18c98249ae72c3c7188bdd9dceff2840585227f79843" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - shelf: - dependency: transitive - description: - name: shelf - sha256: c2f658d28ec86857657dec3579e2db4dc5a6c477b6aecde870e77f0682258901 - url: "https://pub.dev" - source: hosted - version: "1.1.0" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: e0b44ebddec91e70a713e13adf93c1b2100821303b86a18e1ef1d082bd8bd9b8 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: "8584c0aa0f5756a61519b1a2fc2cd22ddbc518e9396bd33ebf06b9836bb23d13" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: fd84910bf7d58db109082edf7326b75322b8f186162028482f53dc892f00332d - url: "https://pub.dev" - source: hosted - version: "1.0.1" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: "8c463326277f68a628abab20580047b419c2ff66756fd0affd451f73f9508c11" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "52de2200bb098de739794c82d09c41ac27b2e42fd7e23cce7b9c74bf653c7296" - url: "https://pub.dev" - source: hosted - version: "0.10.10" - source_span: - dependency: transitive - description: - name: source_span - sha256: d5f89a9e52b36240a80282b3dc0667dd36e53459717bb17b8fb102d30496606a - url: "https://pub.dev" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: f8d9f247e2f9f90e32d1495ff32dac7e4ae34ffa7194c5ff8fcc0fd0e52df774 - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: db47e4797198ee601990820437179bb90219f918962318d494ada2b4b11e6f6d - url: "https://pub.dev" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: dd11571b8a03f7cadcf91ec26a77e02bfbd6bbba2a512924d3116646b4198fc4 - url: "https://pub.dev" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a88162591b02c1f3a3db3af8ce1ea2b374bd75a7bb8d5e353bcfbdc79d719830 - url: "https://pub.dev" - source: hosted - version: "1.2.0" - test: - dependency: "direct dev" - description: - name: test - sha256: "51bed717b867dd91d75b804c8abbfb30cf904d30c00bea3d5467f3c3c7d4e064" - url: "https://pub.dev" - source: hosted - version: "1.16.8" - test_api: - dependency: transitive - description: - name: test_api - sha256: "9ddd24ec429417cfffd744115508a95f0ee956ec02a2d972dd7fbfbfe047cf45" - url: "https://pub.dev" - source: hosted - version: "0.3.0" - test_core: - dependency: transitive - description: - name: test_core - sha256: "9567514cac32e25165c78bd2c98092b3f7fd5a1555114b4f08d83830d6645e33" - url: "https://pub.dev" - source: hosted - version: "0.3.19" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - vector_math: - dependency: "direct main" - description: - name: vector_math - sha256: "15cdf04f64b23c2ff6b999c193cbb0c928698dc602ed73075b9562527fcb5bb5" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "422eda09e2a50eb27fe9eca2c897d624cea7fa432a8442e1ea1a10d50a4321ab" - url: "https://pub.dev" - source: hosted - version: "6.2.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "68173f2fa67d241323a4123be7ed4e43424c54befa5505d71c8ad4b7baf8f71d" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: "500e6014efebd305a30ebf1c6006d13faa82dcd85c7a2a7793679a64ed69ec48" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "5adb6ab8ed14e22bb907aae7338f0c206ea21e7a27004e97664b16c120306f00" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" - url: "https://pub.dev" - source: hosted - version: "3.1.0" -sdks: - dart: ">=3.3.0 <4.0.0" From 8c35dc4eaf95d17fe92a89d7b8d63c791cbbd4bd Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:56:23 -0400 Subject: [PATCH 21/28] Pubspec validation --- .../packages/path_parsing/example/pubspec.yaml | 6 +++--- third_party/packages/path_parsing/pubspec.yaml | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/third_party/packages/path_parsing/example/pubspec.yaml b/third_party/packages/path_parsing/example/pubspec.yaml index f854e67d461..dd9a6eef8dc 100644 --- a/third_party/packages/path_parsing/example/pubspec.yaml +++ b/third_party/packages/path_parsing/example/pubspec.yaml @@ -1,9 +1,9 @@ name: path_parsing_example publish_to: none +environment: + sdk: ^3.3.0 + dependencies: path_parsing: path: ../ - -environment: - sdk: '>=2.12.0-0 <3.0.0' diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 4b30a8c243c..58e050e03e9 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -1,8 +1,12 @@ name: path_parsing -version: 1.0.1 description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. -homepage: https://github.com/dnfield/dart_path_parsing +repository: https://github.com/flutter/packages/tree/main/third_party/packages/path_parsing +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_parsing%22 +version: 1.0.1 + +environment: + sdk: ^3.3.0 dependencies: meta: ^1.3.0 @@ -12,5 +16,6 @@ dev_dependencies: path: ^1.8.0 test: ^1.16.0 -environment: - sdk: ^3.3.0 +topics: + - svg + - vector-graphics From d258416273e7d0765ecb2b80da7aad2ae23b6002 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 13:59:08 -0400 Subject: [PATCH 22/28] Version bump --- .../packages/path_parsing/CHANGELOG.md | 31 +++++++++++-------- .../packages/path_parsing/pubspec.yaml | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index cc8f7f3af6c..72251a67cd1 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,42 +1,47 @@ +## 1.0.2 + +* Transfers the package source from https://github.com/google/process.dart to + https://github.com/dnfield/dart_path_parsing. + ## 1.0.1 -- Fix [bug in arc decomposition](https://github.com/dnfield/flutter_svg/issues/742). -- Minor code cleanup for analysis warnings. +* Fix [bug in arc decomposition](https://github.com/dnfield/flutter_svg/issues/742). +* Minor code cleanup for analysis warnings. ## 1.0.0 -- Stable release. +* Stable release. ## 0.2.1 -- Performance improvements to parsing. +* Performance improvements to parsing. ## 0.2.0 -- Stable nullsafe release +* Stable nullsafe release ## 0.2.0-nullsafety.0 -- Nullsafety migration. +* Nullsafety migration. ## 0.1.4 -- Fix implementation of `_PathOffset`'s `==` operator. +* Fix implementation of `_PathOffset`'s `==` operator. ## 0.1.3 -- Fix a bug in decompose cubic curve - avoid trying to call `toInt()` on `double.infinity` -- Bump test dependency. +* Fix a bug in decompose cubic curve - avoid trying to call `toInt()` on `double.infinity` +* Bump test dependency. ## 0.1.2 -- Fix bug with smooth curve commands -- Add deep testing +* Fix bug with smooth curve commands +* Add deep testing ## 0.1.1 -- Fix link to homepage in pubspec, add example +* Fix link to homepage in pubspec, add example ## 0.1.0 -- Initial release, based on the 0.2.4 release of path_drawing +* Initial release, based on the 0.2.4 release of path_drawing diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index 58e050e03e9..49bc7b2b55a 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -3,7 +3,7 @@ description: > A Dart library to help with SVG Path parsing and code generation. Used by Flutter SVG. repository: https://github.com/flutter/packages/tree/main/third_party/packages/path_parsing issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_parsing%22 -version: 1.0.1 +version: 1.0.2 environment: sdk: ^3.3.0 From cc3de83fe443f23cd5c12033e64ecb276f91eda6 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 21 Oct 2024 14:05:25 -0400 Subject: [PATCH 23/28] README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 08507abcb9f..e256308ebee 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ These are the packages hosted in this repository: | [metrics\_center](./packages/metrics_center/) | [![pub package](https://img.shields.io/pub/v/metrics_center.svg)](https://pub.dev/packages/metrics_center) | [![pub points](https://img.shields.io/pub/points/metrics_center)](https://pub.dev/packages/metrics_center/score) | [![popularity](https://img.shields.io/pub/popularity/metrics_center)](https://pub.dev/packages/metrics_center/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20metrics_center?label=)](https://github.com/flutter/flutter/labels/p%3A%20metrics_center) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20metrics_center?label=)](https://github.com/flutter/packages/labels/p%3A%20metrics_center) | | [multicast\_dns](./packages/multicast_dns/) | [![pub package](https://img.shields.io/pub/v/multicast_dns.svg)](https://pub.dev/packages/multicast_dns) | [![pub points](https://img.shields.io/pub/points/multicast_dns)](https://pub.dev/packages/multicast_dns/score) | [![popularity](https://img.shields.io/pub/popularity/multicast_dns)](https://pub.dev/packages/multicast_dns/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20multicast_dns?label=)](https://github.com/flutter/flutter/labels/p%3A%20multicast_dns) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20multicast_dns?label=)](https://github.com/flutter/packages/labels/p%3A%20multicast_dns) | | [palette\_generator](./packages/palette_generator/) | [![pub package](https://img.shields.io/pub/v/palette_generator.svg)](https://pub.dev/packages/palette_generator) | [![pub points](https://img.shields.io/pub/points/palette_generator)](https://pub.dev/packages/palette_generator/score) | [![popularity](https://img.shields.io/pub/popularity/palette_generator)](https://pub.dev/packages/palette_generator/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20palette_generator?label=)](https://github.com/flutter/flutter/labels/p%3A%20palette_generator) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20palette_generator?label=)](https://github.com/flutter/packages/labels/p%3A%20palette_generator) | +| [path\_parsing](./third_party/packages/path_parsing/) | [![pub package](https://img.shields.io/pub/v/path_parsing.svg)](https://pub.dev/packages/path_parsing) | [![pub points](https://img.shields.io/pub/points/path_parsing)](https://pub.dev/packages/path_parsing/score) | [![popularity](https://img.shields.io/pub/popularity/path_parsing)](https://pub.dev/packages/path_parsing/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20path_parsing?label=)](https://github.com/flutter/flutter/labels/p%3A%20path_parsing) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20path_parsing?label=)](https://github.com/flutter/packages/labels/p%3A%20path_parsing) | | [path\_provider](./packages/path_provider/) | [![pub package](https://img.shields.io/pub/v/path_provider.svg)](https://pub.dev/packages/path_provider) | [![pub points](https://img.shields.io/pub/points/path_provider)](https://pub.dev/packages/path_provider/score) | [![popularity](https://img.shields.io/pub/popularity/path_provider)](https://pub.dev/packages/path_provider/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20path_provider?label=)](https://github.com/flutter/flutter/labels/p%3A%20path_provider) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20path_provider?label=)](https://github.com/flutter/packages/labels/p%3A%20path_provider) | | [pigeon](./packages/pigeon/) | [![pub package](https://img.shields.io/pub/v/pigeon.svg)](https://pub.dev/packages/pigeon) | [![pub points](https://img.shields.io/pub/points/pigeon)](https://pub.dev/packages/pigeon/score) | [![popularity](https://img.shields.io/pub/popularity/pigeon)](https://pub.dev/packages/pigeon/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20pigeon?label=)](https://github.com/flutter/flutter/labels/p%3A%20pigeon) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20pigeon?label=)](https://github.com/flutter/packages/labels/p%3A%20pigeon) | | [pointer\_interceptor](./packages/pointer_interceptor/) | [![pub package](https://img.shields.io/pub/v/pointer_interceptor.svg)](https://pub.dev/packages/pointer_interceptor) | [![pub points](https://img.shields.io/pub/points/pointer_interceptor)](https://pub.dev/packages/pointer_interceptor/score) | [![popularity](https://img.shields.io/pub/popularity/pointer_interceptor)](https://pub.dev/packages/pointer_interceptor/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20pointer_interceptor?label=)](https://github.com/flutter/flutter/labels/p%3A%20pointer_interceptor) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20pointer_interceptor?label=)](https://github.com/flutter/packages/labels/p%3A%20pointer_interceptor) | From e7525a13a728255271e16b099119de0699f9ea0b Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 24 Oct 2024 12:23:48 -0400 Subject: [PATCH 24/28] CODEOWNER --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index bfdb5af89d8..00ce7f2d8f3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -28,6 +28,7 @@ packages/local_auth/** @stuartmorgan packages/metrics_center/** @christopherfujino packages/multicast_dns/** @jmagman packages/palette_generator/** @gspencergoog +packages/path_parsing/** @domesticmouse packages/path_provider/** @stuartmorgan packages/pigeon/** @tarrinneal packages/platform/** @stuartmorgan From 299d7afa787609e132a2b75c0012272d57b763c5 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 24 Oct 2024 12:40:27 -0400 Subject: [PATCH 25/28] METADATA file --- CODEOWNERS | 2 +- third_party/packages/path_parsing/METADATA | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 third_party/packages/path_parsing/METADATA diff --git a/CODEOWNERS b/CODEOWNERS index 00ce7f2d8f3..0785e52ba2c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -28,7 +28,6 @@ packages/local_auth/** @stuartmorgan packages/metrics_center/** @christopherfujino packages/multicast_dns/** @jmagman packages/palette_generator/** @gspencergoog -packages/path_parsing/** @domesticmouse packages/path_provider/** @stuartmorgan packages/pigeon/** @tarrinneal packages/platform/** @stuartmorgan @@ -47,6 +46,7 @@ packages/webview_flutter/** @bparrishMines packages/xdg_directories/** @stuartmorgan third_party/packages/cupertino_icons/** @MitchellGoodwin third_party/packages/cupertino_icons/test/goldens/** @LongCatIsLooong +third_party/packages/path_parsing/** @domesticmouse # Plugin platform implementation rules. These should stay last, since the last # matching entry takes precedence. diff --git a/third_party/packages/path_parsing/METADATA b/third_party/packages/path_parsing/METADATA new file mode 100644 index 00000000000..6b54af3ce82 --- /dev/null +++ b/third_party/packages/path_parsing/METADATA @@ -0,0 +1,15 @@ +name: "path_parsing" +description: + "A pure Dart parsing library for SVG paths." + +third_party { + identifier { + type: "Git" + value: "https://github.com/dnfield/dart_path_parsing/" + primary_source: true + version: "6785396f6c5528c720adb14833b196e529e78998" + } + version: "6785396f6c5528c720adb14833b196e529e78998" + last_upgrade_date { year: 2024 month: 10 day: 24 } + license_type: NOTICE +} From dade4c7479fd32a00e1594469bfb3e76df363015 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 24 Oct 2024 13:10:31 -0400 Subject: [PATCH 26/28] Update license check to find and recognize this license --- .../tool/lib/src/license_check_command.dart | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/script/tool/lib/src/license_check_command.dart b/script/tool/lib/src/license_check_command.dart index 5f01cca7b96..40e716591b3 100644 --- a/script/tool/lib/src/license_check_command.dart +++ b/script/tool/lib/src/license_check_command.dart @@ -42,6 +42,13 @@ const Set _ignoredFullBasenameList = { 'resource.h', // Generated by VS. }; +// Third-party packages where the code doesn't have file-level annotation, just +// the package-level LICENSE file. Each entry must be a directory relative to +// third_party/packages, as that is the only directory where this is allowed. +const Set _unannotatedFileThirdPartyDirectories = { + 'path_parsing', +}; + // Copyright and license regexes for third-party code. // // These are intentionally very simple, since there is very little third-party @@ -69,6 +76,16 @@ final List _thirdPartyLicenseBlockRegexes = [ r'// Use of this source code is governed by a BSD-style license that can be\n' r'// found in the LICENSE file\.\n', ), + // packages/third_party/path_parsing. + RegExp( + r'Copyright \(c\) 2018 Dan Field\n\n' + r'Permission is hereby granted, free of charge, to any person obtaining a copy\n' + r'of this software and associated documentation files \(the "Software"\), to deal\n' + r'in the Software without restriction, including without limitation the rights\n' + r'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n' + r'copies of the Software, and to permit persons to whom the Software is\n' + r'furnished to do so, subject to the following conditions:', + ), ]; // The exact format of the BSD license that our license files should contain. @@ -217,10 +234,26 @@ class LicenseCheckCommand extends PackageCommand { for (final File file in codeFiles) { print('Checking ${file.path}'); + // Some third-party directories have code that doesn't annotate each file, + // so for those check the LICENSE file instead. This is done even though + // it's redundant to re-check it for each file because it ensures that we + // are still validating every file individually, rather than having a + // codepath where whole directories of files are ignored, which would have + // a much worse failure mode. + String content; + if (_unannotatedFileThirdPartyDirectories.any( + (String dir) => file.path.contains('/third_party/packages/$dir/'))) { + Directory packageDir = file.parent; + while (packageDir.parent.basename != 'packages') { + packageDir = packageDir.parent; + } + content = await packageDir.childFile('LICENSE').readAsString(); + } else { + content = await file.readAsString(); + } // On Windows, git may auto-convert line endings on checkout; this should // still pass since they will be converted back on commit. - final String content = - (await file.readAsString()).replaceAll('\r\n', '\n'); + content = content.replaceAll('\r\n', '\n'); final String firstParyLicense = firstPartyLicenseBlockByExtension[p.extension(file.path)] ?? From f4e409a0bc7819ce39555de5cc57883f37fac7f9 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 24 Oct 2024 14:29:52 -0400 Subject: [PATCH 27/28] Autolabeler --- .github/labeler.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index c1a7a366025..ec925d3343e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -138,6 +138,11 @@ - any-glob-to-any-file: - packages/palette_generator/**/* +'p: path_parsing': + - changed-files: + - any-glob-to-any-file: + - third_party/packages/path_parsing/**/* + 'p: path_provider': - changed-files: - any-glob-to-any-file: From ccafa75f96f0b9e67ab293d21721e1ae1f987222 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 25 Oct 2024 09:23:27 -0400 Subject: [PATCH 28/28] README EOL --- third_party/packages/path_parsing/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/packages/path_parsing/README.md b/third_party/packages/path_parsing/README.md index 6088938d213..9f725f69396 100644 --- a/third_party/packages/path_parsing/README.md +++ b/third_party/packages/path_parsing/README.md @@ -2,4 +2,4 @@ Split from the Flutter path drawing library to create a pure Dart parsing library for SVG paths and code generation (without dependencies on Flutter -runtime). \ No newline at end of file +runtime).