Add Path iterator tests, sync verbs with skia enums, fix PathIterator.peek. (flutter/engine#20381)

* Sync verb enum to skia. Fix PathIterator.peek, add tests
* Add constant for iterator buffer size
This commit is contained in:
Ferhat 2020-08-10 17:24:28 -07:00 committed by GitHub
parent 31ca1626ba
commit 39d067388a
5 changed files with 108 additions and 9 deletions

View File

@ -367,7 +367,7 @@ class PathRef {
} else {
_conicWeights!.setAll(0, ref._conicWeights!);
}
assert(verbCount == 0 || _fVerbs[0] != 0);
assert(verbCount == 0 || _fVerbs[0] == ref._fVerbs[0]);
fBoundsIsDirty = ref.fBoundsIsDirty;
if (!fBoundsIsDirty) {
fBounds = ref.fBounds;

View File

@ -15,12 +15,12 @@ class SPathSegmentMask {
/// Types of path operations.
class SPathVerb {
static const int kMove = 1; // 1 point
static const int kLine = 2; // 2 points
static const int kQuad = 3; // 3 points
static const int kConic = 4; // 3 points + 1 weight
static const int kCubic = 5; // 4 points
static const int kClose = 6; // 0 points
static const int kMove = 0; // 1 point
static const int kLine = 1; // 2 points
static const int kQuad = 2; // 3 points
static const int kConic = 3; // 3 points + 1 weight
static const int kCubic = 4; // 4 points
static const int kClose = 5; // 0 points
}
class SPath {

View File

@ -145,7 +145,8 @@ class PathWinding {
}
_QuadRoots quadRoots = _QuadRoots();
final int n = quadRoots.findRoots(startY - 2 * y1 + endY, 2 * (y1 - startY), endY - y);
final int n = quadRoots.findRoots(
startY - 2 * y1 + endY, 2 * (y1 - startY), endY - y);
assert(n <= 1);
double xt;
if (0 == n) {
@ -377,6 +378,9 @@ class PathIterator {
int _verbIndex = 0;
int _pointIndex = 0;
/// Maximum buffer size required for points in [next] calls.
static const int kMaxBufferSize = 8;
/// Returns true if first contour on path is closed.
bool isClosedContour() {
if (_verbCount == 0 || _verbIndex == _verbCount) {
@ -438,7 +442,17 @@ class PathIterator {
pathRef.points[_pointIndex - 2], pathRef.points[_pointIndex - 1]);
}
int peek() => pathRef._fVerbs[_verbIndex];
int peek() {
if (_verbIndex < pathRef.countVerbs()) {
return pathRef._fVerbs[_verbIndex];
}
if (_needClose && _segmentState == SPathSegmentState.kAfterPrimitive) {
return (_lastPointX != _moveToX || _lastPointY != _moveToY)
? SPath.kLineVerb
: SPath.kCloseVerb;
}
return SPath.kDoneVerb;
}
// Returns next verb and reads associated points into [outPts].
int next(Float32List outPts) {

View File

@ -0,0 +1,85 @@
// 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.
import 'dart:typed_data';
import 'package:ui/src/engine.dart';
import 'package:test/test.dart';
void main() {
final Float32List points = Float32List(PathIterator.kMaxBufferSize);
group('PathIterator', () {
test('Should return done verb for empty path', () {
final SurfacePath path = SurfacePath();
final PathIterator iter = PathIterator(path.pathRef, false);
expect(iter.peek(), SPath.kDoneVerb);
expect(iter.next(points), SPath.kDoneVerb);
});
test('Should return done when moveTo is last instruction', () {
final SurfacePath path = SurfacePath();
path.moveTo(10, 10);
final PathIterator iter = PathIterator(path.pathRef, false);
expect(iter.peek(), SPath.kMoveVerb);
expect(iter.next(points), SPath.kDoneVerb);
});
test('Should return lineTo', () {
final SurfacePath path = SurfacePath();
path.moveTo(10, 10);
path.lineTo(20, 20);
final PathIterator iter = PathIterator(path.pathRef, false);
expect(iter.peek(), SPath.kMoveVerb);
expect(iter.next(points), SPath.kMoveVerb);
expect(points[0], 10);
expect(iter.next(points), SPath.kLineVerb);
expect(points[2], 20);
expect(iter.next(points), SPath.kDoneVerb);
});
test('Should return extra lineTo if iteration is closed', () {
final SurfacePath path = SurfacePath();
path.moveTo(10, 10);
path.lineTo(20, 20);
final PathIterator iter = PathIterator(path.pathRef, true);
expect(iter.peek(), SPath.kMoveVerb);
expect(iter.next(points), SPath.kMoveVerb);
expect(points[0], 10);
expect(iter.next(points), SPath.kLineVerb);
expect(points[2], 20);
expect(iter.next(points), SPath.kLineVerb);
expect(points[2], 10);
expect(iter.next(points), SPath.kCloseVerb);
expect(iter.next(points), SPath.kDoneVerb);
});
test('Should not return extra lineTo if last point is starting point', () {
final SurfacePath path = SurfacePath();
path.moveTo(10, 10);
path.lineTo(20, 20);
path.lineTo(10, 10);
final PathIterator iter = PathIterator(path.pathRef, true);
expect(iter.peek(), SPath.kMoveVerb);
expect(iter.next(points), SPath.kMoveVerb);
expect(points[0], 10);
expect(iter.next(points), SPath.kLineVerb);
expect(points[2], 20);
expect(iter.next(points), SPath.kLineVerb);
expect(points[2], 10);
expect(iter.next(points), SPath.kCloseVerb);
expect(iter.next(points), SPath.kDoneVerb);
});
test('peek should return lineTo if iteration is closed', () {
final SurfacePath path = SurfacePath();
path.moveTo(10, 10);
path.lineTo(20, 20);
final PathIterator iter = PathIterator(path.pathRef, true);
expect(iter.next(points), SPath.kMoveVerb);
expect(iter.next(points), SPath.kLineVerb);
expect(iter.peek(), SPath.kLineVerb);
});
});
}