| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // @dart = 2.6 |
| part of ui; |
| |
| /// 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. |
| /// |
| /// This iterable does not memoize. Callers who need to traverse the list |
| /// multiple times, or who need to randomly access elements of the list, should |
| /// use [toList] on this object. |
| abstract class PathMetrics extends collection.IterableBase<PathMetric> { |
| @override |
| Iterator<PathMetric> get iterator; |
| } |
| |
| /// Used by [PathMetrics] to track iteration from one segment of a path to the |
| /// next for measurement. |
| abstract class PathMetricIterator implements Iterator<PathMetric> { |
| @override |
| PathMetric get current; |
| |
| @override |
| bool moveNext(); |
| } |
| |
| /// Utilities for measuring a [Path] and extracting sub-paths. |
| /// |
| /// Iterate over the object returned by [Path.computeMetrics] to obtain |
| /// [PathMetric] objects. Callers that want to randomly access elements or |
| /// iterate multiple times should use `path.computeMetrics().toList()`, since |
| /// [PathMetrics] does not memoize. |
| /// |
| /// Once created, the metrics are only valid for the path as it was specified |
| /// when [Path.computeMetrics] was called. If additional contours are added or |
| /// any contours are updated, the metrics need to be recomputed. Previously |
| /// created metrics will still refer to a snapshot of the path at the time they |
| /// were computed, rather than to the actual metrics for the new mutations to |
| /// the path. |
| /// |
| /// Implementation is based on |
| /// https://github.com/google/skia/blob/master/src/core/SkContourMeasure.cpp |
| /// to maintain consistency with native platforms. |
| abstract class PathMetric { |
| /// Return the total length of the current contour. |
| double get length; |
| |
| /// The zero-based index of the contour. |
| /// |
| /// [Path] objects are made up of zero or more contours. The first contour is |
| /// created once a drawing command (e.g. [Path.lineTo]) is issued. A |
| /// [Path.moveTo] command after a drawing command may create a new contour, |
| /// although it may not if optimizations are applied that determine the move |
| /// command did not actually result in moving the pen. |
| /// |
| /// This property is only valid with reference to its original iterator and |
| /// the contours of the path at the time the path's metrics were computed. If |
| /// additional contours were added or existing contours updated, this metric |
| /// will be invalid for the current state of the path. |
| int get contourIndex; |
| |
| /// 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); |
| |
| /// 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}); |
| |
| /// 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; |
| } |
| |
| /// 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 Tangent(position, 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); |
| } |