Skip to content

Commit

Permalink
Revert "Add support for measuring, combining, and getting bounds of P…
Browse files Browse the repository at this point in the history
…ath objects " (flutter#4954)

* Revert "Add support for measuring, combining, and getting bounds of Path objects  (flutter#4799)"

This reverts commit 8c00101, as it broke engine build bots on Linux and Windows.
  • Loading branch information
alexmarkov authored Apr 9, 2018
1 parent 4492730 commit 3cc6c67
Show file tree
Hide file tree
Showing 10 changed files with 11 additions and 758 deletions.
2 changes: 0 additions & 2 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 0 additions & 2 deletions lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
306 changes: 10 additions & 296 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
Expand Down Expand Up @@ -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_.
Expand All @@ -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].
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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<PathMetric> {
PathMetrics._(Path path, bool forceClosed) :
_iterator = new PathMetricIterator._(new PathMetric._(path, forceClosed));

final Iterator<PathMetric> _iterator;

@override
Iterator<PathMetric> get iterator => _iterator;
}

/// Tracks iteration from one segment of a path to the next for measurement.
class PathMetricIterator implements Iterator<PathMetric> {
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.
Expand Down
Loading

0 comments on commit 3cc6c67

Please sign in to comment.