diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 57824f8e1ec3c..8b3be72d5973b 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -36,8 +36,6 @@ source_set("ui") { "painting/paint.h", "painting/path.cc", "painting/path.h", - "painting/path_measure.cc", - "painting/path_measure.h", "painting/picture.cc", "painting/picture.h", "painting/picture_recorder.cc", diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index 824152e28e8d0..59d083a191778 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -15,7 +15,6 @@ #include "flutter/lib/ui/painting/image_filter.h" #include "flutter/lib/ui/painting/image_shader.h" #include "flutter/lib/ui/painting/path.h" -#include "flutter/lib/ui/painting/path_measure.h" #include "flutter/lib/ui/painting/picture.h" #include "flutter/lib/ui/painting/picture_recorder.h" #include "flutter/lib/ui/painting/vertices.h" @@ -54,7 +53,6 @@ void DartUI::InitForGlobal() { CanvasGradient::RegisterNatives(g_natives); CanvasImage::RegisterNatives(g_natives); CanvasPath::RegisterNatives(g_natives); - CanvasPathMeasure::RegisterNatives(g_natives); Codec::RegisterNatives(g_natives); DartRuntimeHooks::RegisterNatives(g_natives); FrameInfo::RegisterNatives(g_natives); diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart index a26cdf9ac87bd..02c4b4986e194 100644 --- a/lib/ui/painting.dart +++ b/lib/ui/painting.dart @@ -39,12 +39,6 @@ bool _offsetIsValid(Offset offset) { return true; } -bool _matrix4IsValid(Float64List matrix4) { - assert(matrix4 != null, 'Matrix4 argument was null.'); - assert(matrix4.length == 16, 'Matrix4 must have 16 entries.'); - return true; -} - bool _radiusIsValid(Radius radius) { assert(radius != null, 'Radius argument was null.'); assert(!radius.x.isNaN && !radius.y.isNaN, 'Radius argument contained a NaN value.'); @@ -1437,62 +1431,6 @@ enum PathFillType { evenOdd, } -/// Strategies for combining paths. -/// -/// See also: -/// -/// * [Path.combine], which uses this enum to decide how to combine two paths. -// Must be kept in sync with SkPathOp -enum PathOperation { - /// Subtract the second path from the first path. - /// - /// For example, if the two paths are overlapping circles of equal diameter - /// but differing centers, the result would be a crescent portion of the - /// first circle that was not overlapped by the second circle. - /// - /// See also: - /// - /// * [reverseDifference], which is the same but subtracting the first path - /// from the second. - difference, - /// Create a new path that is the intersection of the two paths, leaving the - /// overlapping pieces of the path. - /// - /// For example, if the two paths are overlapping circles of equal diameter - /// but differing centers, the result would be only the overlapping portion - /// of the two circles. - /// - /// See also: - /// * [xor], which is the inverse of this operation - intersect, - /// Create a new path that is the union (inclusive-or) of the two paths. - /// - /// For example, if the two paths are overlapping circles of equal diameter - /// but differing centers, the result would be a figure-eight like shape - /// matching the outter boundaries of both circles. - union, - /// Create a new path that is the exclusive-or of the two paths, leaving - /// everything but the overlapping pieces of the path. - /// - /// For example, if the two paths are overlapping circles of equal diameter - /// but differing centers, the figure-eight like shape less the overlapping parts - /// - /// See also: - /// * [intersect], which is the inverse of this operation - xor, - /// Subtract the first path from the second path. - /// - /// For example, if the two paths are overlapping circles of equal diameter - /// but differing centers, the result would be a crescent portion of the - /// second circle that was not overlapped by the first circle. - /// - /// See also: - /// - /// * [difference], which is the same but subtracting the second path - /// from the frist. - reverseDifference, -} - /// A complex, one-dimensional subset of a plane. /// /// A path consists of a number of subpaths, and a _current point_. @@ -1515,15 +1453,6 @@ class Path extends NativeFieldWrapperClass2 { Path() { _constructor(); } void _constructor() native 'Path_constructor'; - /// Creates a copy of another [Path]. - /// - /// This copy is fast and does not require additional memory unless either - /// the `source` path or the path returned by this constructor are modified. - factory Path.from(Path source) { - return source._clone(); - } - Path _clone() native 'Path_clone'; - /// Determines how the interior of this path is calculated. /// /// Defaults to the non-zero winding rule, [PathFillType.nonZero]. @@ -1721,43 +1650,23 @@ class Path extends NativeFieldWrapperClass2 { } void _addRRect(Float32List rrect) native 'Path_addRRect'; - /// Adds a new subpath that consists of the given `path` offset by the given - /// `offset`. - /// - /// If `matrix4` is specified, the path will be transformed by this matrix - /// after the matrix is translated by the given offset. The matrix is a 4x4 - /// matrix stored in column major order. - void addPath(Path path, Offset offset, {Float64List matrix4}) { + /// Adds a new subpath that consists of the given path offset by the given + /// offset. + void addPath(Path path, Offset offset) { assert(path != null); // path is checked on the engine side assert(_offsetIsValid(offset)); - if (matrix4 != null) { - assert(_matrix4IsValid(matrix4)); - _addPathWithMatrix(path, offset.dx, offset.dy, matrix4); - } else { - _addPath(path, offset.dx, offset.dy); - } + _addPath(path, offset.dx, offset.dy); } void _addPath(Path path, double dx, double dy) native 'Path_addPath'; - void _addPathWithMatrix(Path path, double dx, double dy, Float64List matrix) native 'Path_addPathWithMatrix'; - + /// Adds the given path to this path by extending the current segment of this /// path with the the first segment of the given path. - /// - /// If `matrix4` is specified, the path will be transformed by this matrix - /// after the matrix is translated by the given `offset`. The matrix is a 4x4 - /// matrix stored in column major order. - void extendWithPath(Path path, Offset offset, {Float64List matrix4}) { + void extendWithPath(Path path, Offset offset) { assert(path != null); // path is checked on the engine side assert(_offsetIsValid(offset)); - if (matrix4 != null) { - assert(_matrix4IsValid(matrix4)); - _extendWithPathAndMatrix(path, offset.dx, offset.dy, matrix4); - } else { - _extendWithPath(path, offset.dx, offset.dy); - } + _extendWithPath(path, offset.dx, offset.dy); } void _extendWithPath(Path path, double dx, double dy) native 'Path_extendWithPath'; - void _extendWithPathAndMatrix(Path path, double dx, double dy, Float64List matrix) native 'Path_extendWithPathAndMatrix'; /// Closes the last subpath, as if a straight line had been drawn /// from the current point to the first point of the subpath. @@ -1792,207 +1701,12 @@ class Path extends NativeFieldWrapperClass2 { /// Returns a copy of the path with all the segments of every /// subpath transformed by the given matrix. Path transform(Float64List matrix4) { - assert(_matrix4IsValid(matrix4)); + assert(matrix4 != null); + if (matrix4.length != 16) + throw new ArgumentError('"matrix4" must have 16 entries.'); return _transform(matrix4); } Path _transform(Float64List matrix4) native 'Path_transform'; - - /// Computes the bounding rectangle for this path. - Rect getBounds() { - final Float32List rect = _getBounds(); - return new Rect.fromLTRB(rect[0], rect[1], rect[2], rect[3]); - } - Float32List _getBounds() native 'Path_getBounds'; - - /// Combines the two paths according to the manner specified by the given - /// `operation`. - /// - /// The resulting path will be constructed from non-overlapping contours. The - /// curve order is reduced where possible so that cubics may be turned into - /// quadratics, and quadratics maybe turned into lines. - static Path combine(PathOperation operation, Path path1, Path path2) { - assert(path1 != null); - assert(path2 != null); - final Path path = new Path(); - if (path._op(path1, path2, operation.index)) { - return path; - } - throw new StateError('Path.combine() failed. This may be due an invalid path; in particular, check for NaN values.'); - } - bool _op(Path path1, Path path2, int operation) native 'Path_op'; - - /// Creates a [PathMetrics] object for this path. - /// - /// If `forceClosed` is set to true, the contours of the path will be measured - /// as if they had been closed, even if they were not explicitly closed. - PathMetrics computeMetrics({bool forceClosed: false}) { - return new PathMetrics._(this, forceClosed); - } -} - -/// The geometric description of a tangent: the angle at a point. -/// -/// See also: -/// * [PathMetric.getTangentForOffset], which returns the tangent of an offset along a path. -class Tangent { - /// Creates a [Tangent] with the given values. - /// - /// The arguments must not be null. - const Tangent(this.position, this.vector) - : assert(position != null), - assert(vector != null); - - /// Creates a [Tangent] based on the angle rather than the vector. - /// - /// The [vector] is computed to be the unit vector at the given angle, interpreted - /// as clockwise radians from the x axis. - factory Tangent.fromAngle(Offset position, double angle) { - return new Tangent(position, new Offset(math.cos(angle), math.sin(angle))); - } - - /// Position of the tangent. - /// - /// When used with [PathMetric.getTangentForOffset], this represents the precise - /// position that the given offset along the path corresponds to. - final Offset position; - - /// The vector of the curve at [position]. - /// - /// When used with [PathMetric.getTangentForOffset], this is the vector of the - /// curve that is at the given offset along the path (i.e. the direction of the - /// curve at [position]). - final Offset vector; - - /// The direction of the curve at [position]. - /// - /// When used with [PathMetric.getTangentForOffset], this is the angle of the - /// curve that is the given offset along the path (i.e. the direction of the - /// curve at [position]). - /// - /// This value is in radians, with 0.0 meaning pointing along the x axis in - /// the positive x-axis direction, positive numbers pointing downward toward - /// the negative y-axis, i.e. in a clockwise direction, and negative numbers - /// pointing upward toward the positive y-axis, i.e. in a counter-clockwise - /// direction. - // flip the sign to be consistent with [Path.arcTo]'s `sweepAngle` - double get angle => -math.atan2(vector.dy, vector.dx); -} - -/// An iterable collection of [PathMetric] objects describing a [Path]. -/// -/// A [PathMetrics] object is created by using the [Path.computeMetrics] method, -/// and represents the path as it stood at the time of the call. Subsequent -/// modifications of the path do not affect the [PathMetrics] object. -/// -/// Each path metric corresponds to a segment, or contour, of a path. -/// -/// For example, a path consisting of a [Path.lineTo], a [Path.moveTo], and -/// another [Path.lineTo] will contain two contours and thus be represented by -/// two [PathMetric] objects. -/// -/// When iterating across a [PathMetrics]' contours, the [PathMetric] objects are only -/// valid until the next one is obtained. -class PathMetrics extends collection.IterableBase { - PathMetrics._(Path path, bool forceClosed) : - _iterator = new PathMetricIterator._(new PathMetric._(path, forceClosed)); - - final Iterator _iterator; - - @override - Iterator get iterator => _iterator; -} - -/// Tracks iteration from one segment of a path to the next for measurement. -class PathMetricIterator implements Iterator { - PathMetricIterator._(this._pathMetric); - - PathMetric _pathMetric; - bool _firstTime = true; - - @override - PathMetric get current => _firstTime ? null : _pathMetric; - - @override - bool moveNext() { - // PathMetric isn't a normal iterable - it's already initialized to its - // first Path. Should only call _moveNext when done with the first one. - if (_firstTime == true) { - _firstTime = false; - return true; - } else if (_pathMetric?._moveNext() == true) { - return true; - } - _pathMetric = null; - return false; - } -} - -/// Utilities for measuring a [Path] and extracting subpaths. -/// -/// Iterate over the object returned by [Path.computeMetrics] to obtain -/// [PathMetric] objects. -/// -/// Once created, metrics will only be valid while the iterator is at the given -/// contour. When the next contour's [PathMetric] is obtained, this object -/// becomes invalid. -class PathMetric extends NativeFieldWrapperClass2 { - /// Create a new empty [Path] object. - PathMetric._(Path path, bool forceClosed) { _constructor(path, forceClosed); } - void _constructor(Path path, bool forceClosed) native 'PathMeasure_constructor'; - - /// Return the total length of the current contour. - double get length native 'PathMeasure_getLength'; - - /// Computes the position of hte current contour at the given offset, and the - /// angle of the path at that point. - /// - /// For example, calling this method with a distance of 1.41 for a line from - /// 0.0,0.0 to 2.0,2.0 would give a point 1.0,1.0 and the angle 45 degrees - /// (but in radians). - /// - /// Returns null if the contour has zero [length]. - /// - /// The distance is clamped to the [length] of the current contour. - Tangent getTangentForOffset(double distance) { - final Float32List posTan = _getPosTan(distance); - // first entry == 0 indicates that Skia returned false - if (posTan[0] == 0.0) { - return null; - } else { - return new Tangent( - new Offset(posTan[1], posTan[2]), - new Offset(posTan[3], posTan[4]) - ); - } - } - Float32List _getPosTan(double distance) native 'PathMeasure_getPosTan'; - - /// Given a start and stop distance, return the intervening segment(s). - /// - /// `start` and `end` are pinned to legal values (0..[length]) - /// Returns null if the segment is 0 length or `start` > `stop`. - /// Begin the segment with a moveTo if `startWithMoveTo` is true. - Path extractPath(double start, double end, {bool startWithMoveTo: true}) native 'PathMeasure_getSegment'; - - /// Whether the contour is closed. - /// - /// Returns true if the contour ends with a call to [Path.close] (which may - /// have been implied when using [Path.addRect]) or if `forceClosed` was - /// specified as true in the call to [Path.computeMetrics]. Returns false - /// otherwise. - bool get isClosed native 'PathMeasure_isClosed'; - - // Move to the next contour in the path. - // - // A path can have a next contour if [Path.moveTo] was called after drawing began. - // Return true if one exists, or false. - // - // This is not exactly congruent with a regular [Iterator.moveNext]. - // Typically, [Iterator.moveNext] should be called before accessing the - // [Iterator.current]. In this case, the [PathMetric] is valid before - // calling `_moveNext` - `_moveNext` should be called after the first - // iteration is done instead of before. - bool _moveNext() native 'PathMeasure_nextContour'; } /// Styles to use for blurs in [MaskFilter] objects. diff --git a/lib/ui/painting/path.cc b/lib/ui/painting/path.cc index ffd9f4b7c5b02..ee85ca2c69431 100644 --- a/lib/ui/painting/path.cc +++ b/lib/ui/painting/path.cc @@ -38,7 +38,6 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, Path); V(Path, contains) \ V(Path, cubicTo) \ V(Path, extendWithPath) \ - V(Path, extendWithPathAndMatrix) \ V(Path, getFillType) \ V(Path, lineTo) \ V(Path, moveTo) \ @@ -52,11 +51,7 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, Path); V(Path, reset) \ V(Path, setFillType) \ V(Path, shift) \ - V(Path, transform) \ - V(Path, getBounds) \ - V(Path, addPathWithMatrix) \ - V(Path, op) \ - V(Path, clone) + V(Path, transform) FOR_EACH_BINDING(DART_NATIVE_CALLBACK) @@ -212,17 +207,6 @@ void CanvasPath::addPath(CanvasPath* path, double dx, double dy) { path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); } -void CanvasPath::addPathWithMatrix(CanvasPath* path, double dx, double dy, tonic::Float64List& matrix4) { - if (!path) - Dart_ThrowException(ToDart("Path.addPathWithMatrix called with non-genuine Path.")); - - SkMatrix matrix = ToSkMatrix(matrix4); - matrix.setTranslateX(matrix.getTranslateX() + dx); - matrix.setTranslateY(matrix.getTranslateY() + dy); - path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); - matrix4.Release(); -} - void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { if (!path) Dart_ThrowException( @@ -230,17 +214,6 @@ void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); } -void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, double dx, double dy, tonic::Float64List& matrix4) { - if (!path) - Dart_ThrowException(ToDart("Path.addPathWithMatrix called with non-genuine Path.")); - - SkMatrix matrix = ToSkMatrix(matrix4); - matrix.setTranslateX(matrix.getTranslateX() + dx); - matrix.setTranslateY(matrix.getTranslateY() + dy); - path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); - matrix4.Release(); -} - void CanvasPath::close() { path_.close(); } @@ -266,27 +239,4 @@ fxl::RefPtr CanvasPath::transform(tonic::Float64List& matrix4) { return path; } -tonic::Float32List CanvasPath::getBounds() { - tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4)); - const SkRect& bounds = path_.getBounds(); - rect[0] = bounds.left(); - rect[1] = bounds.top(); - rect[2] = bounds.right(); - rect[3] = bounds.bottom(); - return rect; -} - - -bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) { - return Op(path1->path(), path2->path(), (SkPathOp)operation, &path_); -} - -fxl::RefPtr CanvasPath::clone() { - fxl::RefPtr path = CanvasPath::Create(); - // per Skia docs, this will create a fast copy - // data is shared until the source path or dest path are mutated - path->path_ = path_; - return path; -} - } // namespace blink diff --git a/lib/ui/painting/path.h b/lib/ui/painting/path.h index afe670b72ff20..900ca0e3f57ef 100644 --- a/lib/ui/painting/path.h +++ b/lib/ui/painting/path.h @@ -10,7 +10,6 @@ #include "lib/tonic/typed_data/float32_list.h" #include "lib/tonic/typed_data/float64_list.h" #include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/pathops/SkPathOps.h" namespace tonic { class DartLibraryNatives; @@ -29,12 +28,6 @@ class CanvasPath : public fxl::RefCountedThreadSafe, return fxl::MakeRefCounted(); } - static fxl::RefPtr CreateFrom(const SkPath& src) { - fxl::RefPtr path = CanvasPath::Create(); - path->path_ = src; - return path; - } - int getFillType(); void setFillType(int fill_type); @@ -85,23 +78,12 @@ class CanvasPath : public fxl::RefCountedThreadSafe, void addPolygon(const tonic::Float32List& points, bool close); void addRRect(const RRect& rrect); void addPath(CanvasPath* path, double dx, double dy); - void addPathWithMatrix(CanvasPath* path, - double dx, - double dy, - tonic::Float64List& matrix4); void extendWithPath(CanvasPath* path, double dx, double dy); - void extendWithPathAndMatrix(CanvasPath* path, - double dx, - double dy, - tonic::Float64List& matrix4); void close(); void reset(); bool contains(double x, double y); fxl::RefPtr shift(double dx, double dy); fxl::RefPtr transform(tonic::Float64List& matrix4); - tonic::Float32List getBounds(); - bool op(CanvasPath* path1, CanvasPath* path2, int operation); - fxl::RefPtr clone(); const SkPath& path() const { return path_; } diff --git a/lib/ui/painting/path_measure.cc b/lib/ui/painting/path_measure.cc deleted file mode 100644 index 0260cd3c1c66b..0000000000000 --- a/lib/ui/painting/path_measure.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/lib/ui/painting/path_measure.h" - -#include - -#include "flutter/lib/ui/painting/matrix.h" -#include "lib/tonic/converter/dart_converter.h" -#include "lib/tonic/dart_args.h" -#include "lib/tonic/dart_binding_macros.h" -#include "lib/tonic/dart_library_natives.h" - -using tonic::ToDart; - -namespace blink { - -typedef CanvasPathMeasure PathMeasure; - -static void PathMeasure_constructor(Dart_NativeArguments args) { - DartCallConstructor(&CanvasPathMeasure::Create, args); -} - -IMPLEMENT_WRAPPERTYPEINFO(ui, PathMeasure); - -#define FOR_EACH_BINDING(V) \ - V(PathMeasure, setPath) \ - V(PathMeasure, getLength) \ - V(PathMeasure, getPosTan) \ - V(PathMeasure, getSegment) \ - V(PathMeasure, isClosed) \ - V(PathMeasure, nextContour) - -FOR_EACH_BINDING(DART_NATIVE_CALLBACK) - -void CanvasPathMeasure::RegisterNatives(tonic::DartLibraryNatives* natives) { - natives->Register( - {{"PathMeasure_constructor", PathMeasure_constructor, 3, true}, - FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); -} - -fxl::RefPtr CanvasPathMeasure::Create(const CanvasPath* path, - bool forceClosed) { - fxl::RefPtr pathMeasure = - fxl::MakeRefCounted(); - if (path) { - const SkPath skPath = path->path(); - pathMeasure->path_measure_ = - std::make_unique(skPath, forceClosed, 1); - } else { - pathMeasure->path_measure_ = std::make_unique(); - } - return pathMeasure; -} - -CanvasPathMeasure::CanvasPathMeasure() {} - -CanvasPathMeasure::~CanvasPathMeasure() {} - -void CanvasPathMeasure::setPath(const CanvasPath* path, bool isClosed) { - const SkPath* skPath = &(path->path()); - path_measure_->setPath(skPath, isClosed); -} - -float CanvasPathMeasure::getLength() { - return path_measure_->getLength(); -} - -tonic::Float32List CanvasPathMeasure::getPosTan(float distance) { - SkPoint pos; - SkVector tan; - bool success = path_measure_->getPosTan(distance, &pos, &tan); - - tonic::Float32List posTan(Dart_NewTypedData(Dart_TypedData_kFloat32, 5)); - if (success) { - posTan[0] = 1; // dart code will check for this for success - posTan[1] = pos.x(); - posTan[2] = pos.y(); - posTan[3] = tan.x(); - posTan[4] = tan.y(); - } else { - posTan[0] = 0; // dart code will check for this for failure - } - - return posTan; -} - -fxl::RefPtr CanvasPathMeasure::getSegment(float startD, - float stopD, - bool startWithMoveTo) { - SkPath dst; - bool success = - path_measure_->getSegment(startD, stopD, &dst, startWithMoveTo); - if (!success) { - return CanvasPath::Create(); - } else { - return CanvasPath::CreateFrom(dst); - } -} - -bool CanvasPathMeasure::isClosed() { - return path_measure_->isClosed(); -} - -bool CanvasPathMeasure::nextContour() { - return path_measure_->nextContour(); -} - -} // namespace blink diff --git a/lib/ui/painting/path_measure.h b/lib/ui/painting/path_measure.h deleted file mode 100644 index 7862081a88ec1..0000000000000 --- a/lib/ui/painting/path_measure.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_LIB_UI_PAINTING_PATH_MEASURE_H_ -#define FLUTTER_LIB_UI_PAINTING_PATH_MEASURE_H_ - -#include "flutter/lib/ui/painting/path.h" -#include "lib/tonic/dart_wrappable.h" -#include "lib/tonic/typed_data/float64_list.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkPathMeasure.h" - -namespace tonic { -class DartLibraryNatives; -} // namespace tonic - -// Be sure that the client doesn't modify a path on us before Skia finishes -// See AOSP's reasoning in PathMeasure.cpp - -namespace blink { - -class CanvasPathMeasure : public fxl::RefCountedThreadSafe, - public tonic::DartWrappable { - DEFINE_WRAPPERTYPEINFO(); - FRIEND_MAKE_REF_COUNTED(CanvasPathMeasure); - - public: - ~CanvasPathMeasure() override; - static fxl::RefPtr Create(const CanvasPath* path, bool forceClosed); - - void setPath(const CanvasPath* path, bool isClosed); - float getLength(); - tonic::Float32List getPosTan(float distance); - fxl::RefPtr getSegment(float startD, float stopD, bool startWithMoveTo); - bool isClosed(); - bool nextContour(); - - static void RegisterNatives(tonic::DartLibraryNatives* natives); - - const SkPathMeasure& pathMeasure() const { return *path_measure_; } - - private: - CanvasPathMeasure(); - - std::unique_ptr path_measure_; -}; - -} // namespace blink - -#endif // FLUTTER_LIB_UI_PAINTING_PATH_MEASURE_H_ diff --git a/lib/ui/ui.dart b/lib/ui/ui.dart index 149cbde2101d4..5d6bc3ef21306 100644 --- a/lib/ui/ui.dart +++ b/lib/ui/ui.dart @@ -13,7 +13,6 @@ library dart.ui; import 'dart:_internal' hide Symbol; import 'dart:async'; -import 'dart:collection' as collection; import 'dart:convert'; import 'dart:developer' as developer; import 'dart:math' as math; diff --git a/testing/dart/path_test.dart b/testing/dart/path_test.dart deleted file mode 100644 index 2ce334c416e21..0000000000000 --- a/testing/dart/path_test.dart +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:typed_data' show Float64List; -import 'dart:ui'; - -import 'package:test/test.dart'; - -Matcher moreOrLessEquals(double value, {double epsilon: 1e-10}) { - return new _MoreOrLessEquals(value, epsilon); -} - -class _MoreOrLessEquals extends Matcher { - const _MoreOrLessEquals(this.value, this.epsilon); - - final double value; - final double epsilon; - - @override - bool matches(Object object, Map matchState) { - if (object is! double) return false; - if (object == value) return true; - final double test = object; - return (test - value).abs() <= epsilon; - } - - @override - Description describe(Description description) => - description.add('$value (±$epsilon)'); -} - -void main() { - test('path getBounds', () { - final Rect r = new Rect.fromLTRB(1.0, 3.0, 5.0, 7.0); - final Path p = new Path()..addRect(r); - expect(p.getBounds(), equals(r)); - p.lineTo(20.0, 15.0); - expect(p.getBounds(), equals(new Rect.fromLTRB(1.0, 3.0, 20.0, 15.0))); - }); - - test('path combine rect', () { - final Rect c1 = - new Rect.fromCircle(center: const Offset(10.0, 10.0), radius: 10.0); - final Rect c2 = - new Rect.fromCircle(center: const Offset(5.0, 5.0), radius: 10.0); - final Rect c1UnionC2 = c1.expandToInclude(c2); - final Rect c1IntersectC2 = c1.intersect(c2); - final Path pathCircle1 = new Path()..addRect(c1); - final Path pathCircle2 = new Path()..addRect(c2); - - final Path difference = - Path.combine(PathOperation.difference, pathCircle1, pathCircle2); - expect(difference.getBounds(), equals(c1)); - - final Path reverseDifference = - Path.combine(PathOperation.reverseDifference, pathCircle1, pathCircle2); - expect(reverseDifference.getBounds(), equals(c2)); - - final Path union = - Path.combine(PathOperation.union, pathCircle1, pathCircle2); - expect(union.getBounds(), equals(c1UnionC2)); - - final Path intersect = - Path.combine(PathOperation.intersect, pathCircle1, pathCircle2); - expect(intersect.getBounds(), equals(c1IntersectC2)); - - // the bounds on this will be the same as union - but would draw a missing inside piece. - final Path xor = Path.combine(PathOperation.xor, pathCircle1, pathCircle2); - expect(xor.getBounds(), equals(c1UnionC2)); - }); - - test('path combine oval', () { - final Rect c1 = - new Rect.fromCircle(center: const Offset(10.0, 10.0), radius: 10.0); - final Rect c2 = - new Rect.fromCircle(center: const Offset(5.0, 5.0), radius: 10.0); - final Rect c1UnionC2 = c1.expandToInclude(c2); - final Rect c1IntersectC2 = c1.intersect(c2); - final Path pathCircle1 = new Path()..addOval(c1); - final Path pathCircle2 = new Path()..addOval(c2); - - final Path difference = - Path.combine(PathOperation.difference, pathCircle1, pathCircle2); - - expect(difference.getBounds().top, moreOrLessEquals(0.88, epsilon: 0.01)); - - final Path reverseDifference = - Path.combine(PathOperation.reverseDifference, pathCircle1, pathCircle2); - expect(reverseDifference.getBounds().right, - moreOrLessEquals(14.11, epsilon: 0.01)); - - final Path union = - Path.combine(PathOperation.union, pathCircle1, pathCircle2); - expect(union.getBounds(), equals(c1UnionC2)); - - final Path intersect = - Path.combine(PathOperation.intersect, pathCircle1, pathCircle2); - expect(intersect.getBounds(), equals(c1IntersectC2)); - - // the bounds on this will be the same as union - but would draw a missing inside piece. - final Path xor = Path.combine(PathOperation.xor, pathCircle1, pathCircle2); - expect(xor.getBounds(), equals(c1UnionC2)); - }); - - test('path clone', () { - final Path p1 = new Path()..lineTo(20.0, 20.0); - final Path p2 = new Path.from(p1); - - expect(p1.getBounds(), equals(p2.getBounds())); - - p1.lineTo(10.0, 30.0); - expect(p1.getBounds().bottom, equals(p2.getBounds().bottom + 10)); - }); - - test('transformation tests', () { - final Rect bounds = new Rect.fromLTRB(0.0, 0.0, 10.0, 10.0); - final Path p = new Path()..addRect(bounds); - final Float64List scaleMatrix = new Float64List.fromList([ - 2.5, 0.0, 0.0, 0.0, // first col - 0.0, 0.5, 0.0, 0.0, // second col - 0.0, 0.0, 1.0, 0.0, // third col - 0.0, 0.0, 0.0, 1.0, // fourth col - ]); - - expect(p.getBounds(), equals(bounds)); - final Path pTransformed = p.transform(scaleMatrix); - - expect(pTransformed.getBounds(), - equals(new Rect.fromLTRB(0.0, 0.0, 10 * 2.5, 10 * 0.5))); - - final Path p2 = new Path()..lineTo(10.0, 10.0); - - p.addPath(p2, const Offset(10.0, 10.0)); - expect(p.getBounds(), equals(new Rect.fromLTRB(0.0, 0.0, 20.0, 20.0))); - - p.addPath(p2, const Offset(20.0, 20.0), matrix4: scaleMatrix); - expect(p.getBounds(), - equals(new Rect.fromLTRB(0.0, 0.0, 20 + (10 * 2.5), 20 + (10 * .5)))); - - p.extendWithPath(p2, const Offset(0.0, 0.0)); - expect(p.getBounds(), equals(new Rect.fromLTRB(0.0, 0.0, 45.0, 25.0))); - - p.extendWithPath(p2, const Offset(45.0, 25.0), matrix4: scaleMatrix); - expect(p.getBounds(), equals(new Rect.fromLTRB(0.0, 0.0, 70.0, 30.0))); - }); - - test('path metrics tests', () { - final Path simpleHorizontalLine = new Path()..lineTo(10.0, 0.0); - - // basic tests on horizontal line - final PathMetrics simpleHorizontalMetrics = - simpleHorizontalLine.computeMetrics(); - expect(simpleHorizontalMetrics.iterator.current, isNull); - expect(simpleHorizontalMetrics.iterator.moveNext(), isTrue); - expect(simpleHorizontalMetrics.iterator.current, isNotNull); - expect(simpleHorizontalMetrics.iterator.current.length, equals(10.0)); - expect(simpleHorizontalMetrics.iterator.current.isClosed, isFalse); - final Path simpleExtract = - simpleHorizontalMetrics.iterator.current.extractPath(1.0, 9.0); - expect(simpleExtract.getBounds(), - equals(new Rect.fromLTRB(1.0, 0.0, 9.0, 0.0))); - final Tangent posTan = - simpleHorizontalMetrics.iterator.current.getTangentForOffset(1.0); - expect(posTan, isNotNull); - expect(posTan.position, equals(const Offset(1.0, 0.0))); - expect(posTan.angle, equals(0.0)); - - expect(simpleHorizontalMetrics.iterator.moveNext(), isFalse); - expect(simpleHorizontalMetrics.iterator.current, isNull); - - // test with forceClosed - final PathMetrics simpleMetricsClosed = - simpleHorizontalLine.computeMetrics(forceClosed: true); - expect(simpleMetricsClosed.iterator.current, isNull); - expect(simpleMetricsClosed.iterator.moveNext(), isTrue); - expect(simpleMetricsClosed.iterator.current, isNotNull); - expect(simpleMetricsClosed.iterator.current.length, - equals(20.0)); // because we forced close - expect(simpleMetricsClosed.iterator.current.isClosed, isTrue); - final Path simpleExtract2 = - simpleMetricsClosed.iterator.current.extractPath(1.0, 9.0); - expect(simpleExtract2.getBounds(), - equals(new Rect.fromLTRB(1.0, 0.0, 9.0, 0.0))); - expect(simpleMetricsClosed.iterator.moveNext(), isFalse); - - // test getTangentForOffset with vertical line - final Path simpleVerticalLine = new Path()..lineTo(0.0, 10.0); - final PathMetrics simpleMetricsVertical = - simpleVerticalLine.computeMetrics()..iterator.moveNext(); - final Tangent posTanVertical = - simpleMetricsVertical.iterator.current.getTangentForOffset(5.0); - expect(posTanVertical.position, equals(const Offset(0.0, 5.0))); - expect(posTanVertical.angle, - moreOrLessEquals(-1.5708, epsilon: .0001)); // 90 degrees - - // test getTangentForOffset with diagonal line - final Path simpleDiagonalLine = new Path()..lineTo(10.0, 10.0); - final PathMetrics simpleMetricsDiagonal = - simpleDiagonalLine.computeMetrics()..iterator.moveNext(); - final double midPoint = simpleMetricsDiagonal.iterator.current.length / 2; - final Tangent posTanDiagonal = - simpleMetricsDiagonal.iterator.current.getTangentForOffset(midPoint); - expect(posTanDiagonal.position, equals(new Offset(5.0, 5.0))); - expect(posTanDiagonal.angle, - moreOrLessEquals(-0.7853981633974483, epsilon: .00001)); // ~45 degrees - - // test a multi-contour path - final Path multiContour = new Path() - ..lineTo(0.0, 10.0) - ..moveTo(10.0, 10.0) - ..lineTo(10.0, 15.0); - - final PathMetrics multiContourMetric = multiContour.computeMetrics(); - expect(multiContourMetric.iterator.current, isNull); - expect(multiContourMetric.iterator.moveNext(), isTrue); - expect(multiContourMetric.iterator.current, isNotNull); - expect(multiContourMetric.iterator.current.length, equals(10.0)); - expect(multiContourMetric.iterator.moveNext(), isTrue); - expect(multiContourMetric.iterator.current, isNotNull); - expect(multiContourMetric.iterator.current.length, equals(5.0)); - expect(multiContourMetric.iterator.moveNext(), isFalse); - expect(multiContourMetric.iterator.current, isNull); - }); -} diff --git a/travis/licenses_golden/licenses_flutter b/travis/licenses_golden/licenses_flutter index 1d9b6410e904f..8749f6880dbf4 100644 --- a/travis/licenses_golden/licenses_flutter +++ b/travis/licenses_golden/licenses_flutter @@ -9845,8 +9845,6 @@ FILE: ../../../flutter/lib/ui/painting/paint.cc FILE: ../../../flutter/lib/ui/painting/paint.h FILE: ../../../flutter/lib/ui/painting/path.cc FILE: ../../../flutter/lib/ui/painting/path.h -FILE: ../../../flutter/lib/ui/painting/path_measure.cc -FILE: ../../../flutter/lib/ui/painting/path_measure.h FILE: ../../../flutter/lib/ui/painting/picture.cc FILE: ../../../flutter/lib/ui/painting/picture.h FILE: ../../../flutter/lib/ui/painting/picture_recorder.cc